Android應用中MVP開發模式


所謂MVP(Model-View-Presenter)模式。是將APP的結構分為三層:

view - UI顯示層

view 層主要負責:

  1. 提供UI交互
  2. 在presenter的控制下修改UI。
  3. 將業務事件交由presenter處理。
    注意. View層不存儲數據,不與Model層交互。

presenter - 邏輯處理層

presenter 層主要負責:

  1. 對UI的各種業務事件進行相應處理。也許是與Model層交互,也許自己進行一些計算,也許控制后台Task,Servic
  2. 對各種訂閱事件進行響應,修改UI。
  3. 臨時存儲頁面相關數據。
    注意. Presenter內不出現View引用。

model - 數據層

model層主要負責:

  1. 從網絡,數據庫,文件,傳感器,第三方等數據源讀寫數據。
  2. 對外部的數據類型進行解析轉換為APP內部數據交由上層處理。
  3. 對數據的臨時存儲,管理,協調上層數據請求。

如圖示,里面的activity,presenter,model均為例子:


mvp

將復雜的功能分割為各層內的小問題。各層內功能單一。這樣易於功能修改拓展與Debug。
解耦的設計,獨立的模塊,更有利於分工開發與測試。

Activity的異常重啟

Activity會在少數情況下被系統重啟:

當用戶旋轉屏幕
在后台時內存不足
改變語言設置
attache 一個外部顯示器等。

正確的方式應該是:
Presenter與Activity的綁定關系應由靜態類管理。而不是由Activity管理。當Activity意外重啟時Presenter不應重啟。Activity重啟時,Presenter與Activity重新綁定,根據數據恢復Activity狀態。
而當Activity真正銷毀時。對應Presenter才應該跟隨銷毀。

當內存不足時,Activity被銷毀其實是整個進程被銷毀。所以Presenter也無能為力。還原時需要重建Presenter。

生命周期

Activity是一個上帝類,其實不適合作為View。所以有些MVP方案將Activity作為Presenter。最主要在於他的生命周期牽扯太多邏輯處理業務。這些由Presenter負責的話情況可以改善很多。我建議將在頂級父類中將activity的生命周期在Presenter中實現一遍,然后生命周期有關的業務邏輯直接由Presenter來實現。

Model的初始化

Model不僅僅是javabean。Model是負責提供各類數據模型。在此基礎上我將Model拓展為數據層提供數據交互。將javabean單獨為數據層的一部分。
Model層的各個Model一般使用單例。這樣的好處在於這個唯一對象可以管理一些數據供所有上層使用。
Model的單例對象

public class UserModel extends AbsModel{ public static UserModel getInstance() { return getInstance(UserModel.class); } @Override protected void onAppCreate(Context ctx) { super.onAppCreate(ctx); //初始化 } public void login(String number,String password,DataCallback<UserDetail> callback){ //進行登錄請求與回調,並保存返回賬號 } public void register(String tel,String password,String code,int gender,String nickname,StatusCallback callback){ //進行注冊請求與回調 } public void findPassword(String number,String code,String password,DataCallback<User> callback){ //進行找回密碼請求與回調 } public void certification(String number,String school,String realName,String stuCard,DataCallback<User> callback){ //進行認證請求與回調 } public void LoginOut(){ //登出操作 } }

既然Model層管理數據,並且是單例。他就有初始化的需求,比如在APP啟動時就請求數據,記錄信息,開始一個后台線程與服務器同步信息等。這些操作與Presenter無關。是數據層自發的的功能。所以需要在Application啟動時進行Model的初始化。
但又要注意不能在Application的onCreate()進行過多操作,否則會啟動時間過長。所以可考慮在啟動時創建一個后台線程,將即時性不強的初始化操作放到后台線程。

Adapter的處理

對於Adapter是放在View好還是Presenter好,這個問題確實難以解決。但在使用解耦的ViewHolder后這個問題便很明了。視圖的創建與改變全由ViewHolder管理。然后Adapter僅僅處理面向ViewHolder的邏輯。
然后ViewHolder屬於View,Adapter屬於Presenter。參考EasyRecyclerView
Adapter:

public class PersonAdapter extends RecyclerArrayAdapter<Person> { public PersonAdapter(Context context) { super(context); } @Override public BaseViewHolder OnCreateViewHolder(ViewGroup parent, int viewType) { return new PersonViewHolder(parent); } }

ViewHolder:

public class PersonViewHolder extends BaseViewHolder<Person> { private TextView mTv_name; private SimpleDraweeView mImg_face; private TextView mTv_sign; public PersonViewHolder(ViewGroup parent) { super(parent,R.layout.item_person); mTv_name = $(R.id.person_name); mTv_sign = $(R.id.person_sign); mImg_face = $(R.id.person_face); } @Override public void setData(final Person person){ mTv_name.setText(person.getName()); mTv_sign.setText(person.getSign()); mImg_face.setImageURI(Uri.parse(person.getFace())); } }

Rx的參與

Rx訂閱發布模式在MVP中作用很大。可以極大簡化層間通訊的處理。View向Presenter訂閱數據。Presenter可以向Model層訂閱數據。形成一個數據鏈。數據可以直接鏈式到達View層。優雅易拓展。
Presenter

public class QuestionShowPresenter extends BeamDataActivityPresenter<QuestionShowActivity,Question> { @Override protected void onCreate(QuestionShowActivity view, Bundle savedState) { super.onCreate(view, savedState); QuestionModel.getInstance().getQuestion(1).subscribe(this); } }

View

public class QuestionShowActivity extends BeamDataActivity<QuestionShowPresenter,Question> { @Override public void setData(Question data) { //顯示數據 } @Override public void setError(Throwable e) { //顯示錯誤 } }

Beam

Beam是我做的一套基於MVP模式的快速開發框架。參考了nucleus。上面的示例代碼都是使用了這個(為方便復制的這個框架demo代碼.= =)。定義了一套開發規范。並提供了基於這套規范的Activity,Fragment,Presenter,Model等父類及控件和API等,完成APP開發過程中大量繁瑣工作。並進行了一系列優化。詳情看這里



文/Jude95(簡書作者)
原文鏈接:http://www.jianshu.com/p/ed2aa9546c2c
著作權歸作者所有,轉載請聯系作者獲得授權,並標注“簡書作者”。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM