所謂MVP(Model-View-Presenter)模式。是將APP的結(jié)構(gòu)分為三層:
view - UI顯示層
view 層主要負責(zé):
- 提供UI交互
- 在presenter的控制下修改UI。
- 將業(yè)務(wù)事件交由presenter處理励饵。
注意. View層不存儲數(shù)據(jù)筛圆,不與Model層交互决摧。
presenter - 邏輯處理層
presenter 層主要負責(zé):
- 對UI的各種業(yè)務(wù)事件進行相應(yīng)處理政基。也許是與Model層交互思杯,也許自己進行一些計算胜蛉,也許控制后臺Task,Servic
- 對各種訂閱事件進行響應(yīng),修改UI誊册。
- 臨時存儲頁面相關(guān)數(shù)據(jù)领突。
注意. Presenter內(nèi)不出現(xiàn)View引用。
model - 數(shù)據(jù)層
model層主要負責(zé):
- 從網(wǎng)絡(luò)案怯,數(shù)據(jù)庫君旦,文件,傳感器殴泰,第三方等數(shù)據(jù)源讀寫數(shù)據(jù)于宙。
- 對外部的數(shù)據(jù)類型進行解析轉(zhuǎn)換為APP內(nèi)部數(shù)據(jù)交由上層處理。
- 對數(shù)據(jù)的臨時存儲,管理悍汛,協(xié)調(diào)上層數(shù)據(jù)請求捞魁。
如圖示,里面的activity离咐,presenter谱俭,model均為例子:

將復(fù)雜的功能分割為各層內(nèi)的小問題。各層內(nèi)功能單一宵蛀。這樣易于功能修改拓展與Debug昆著。
解耦的設(shè)計,獨立的模塊术陶,更有利于分工開發(fā)與測試凑懂。
Activity的異常重啟
Activity會在少數(shù)情況下被系統(tǒng)重啟:
當用戶旋轉(zhuǎn)屏幕
在后臺時內(nèi)存不足
改變語言設(shè)置
attache 一個外部顯示器等。
正確的方式應(yīng)該是:
Presenter與Activity的綁定關(guān)系應(yīng)由靜態(tài)類管理梧宫。而不是由Activity管理接谨。當Activity意外重啟時Presenter不應(yīng)重啟。Activity重啟時塘匣,Presenter與Activity重新綁定脓豪,根據(jù)數(shù)據(jù)恢復(fù)Activity狀態(tài)。
而當Activity真正銷毀時忌卤。對應(yīng)Presenter才應(yīng)該跟隨銷毀扫夜。
當內(nèi)存不足時,Activity被銷毀其實是整個進程被銷毀驰徊。所以Presenter也無能為力笤闯。還原時需要重建Presenter。
生命周期
Activity是一個上帝類棍厂,其實不適合作為View颗味。所以有些MVP方案將Activity作為Presenter。最主要在于他的生命周期牽扯太多邏輯處理業(yè)務(wù)勋桶。這些由Presenter負責(zé)的話情況可以改善很多脱衙。我建議將在頂級父類中將activity的生命周期在Presenter中實現(xiàn)一遍,然后生命周期有關(guān)的業(yè)務(wù)邏輯直接由Presenter來實現(xiàn)例驹。
Model的初始化
Model不僅僅是javabean捐韩。Model是負責(zé)提供各類數(shù)據(jù)模型。在此基礎(chǔ)上我將Model拓展為數(shù)據(jù)層提供數(shù)據(jù)交互鹃锈。將javabean單獨為數(shù)據(jù)層的一部分荤胁。
Model層的各個Model一般使用單例。這樣的好處在于這個唯一對象可以管理一些數(shù)據(jù)供所有上層使用屎债。
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){
//進行登錄請求與回調(diào)仅政,并保存返回賬號
}
public void register(String tel,String password,String code,int gender,String nickname,StatusCallback callback){
//進行注冊請求與回調(diào)
}
public void findPassword(String number,String code,String password,DataCallback<User> callback){
//進行找回密碼請求與回調(diào)
}
public void certification(String number,String school,String realName,String stuCard,DataCallback<User> callback){
//進行認證請求與回調(diào)
}
public void LoginOut(){
//登出操作
}
}
既然Model層管理數(shù)據(jù),并且是單例盆驹。他就有初始化的需求圆丹,比如在APP啟動時就請求數(shù)據(jù),記錄信息躯喇,開始一個后臺線程與服務(wù)器同步信息等辫封。這些操作與Presenter無關(guān)。是數(shù)據(jù)層自發(fā)的的功能廉丽。所以需要在Application啟動時進行Model的初始化倦微。
但又要注意不能在Application的onCreate()進行過多操作,否則會啟動時間過長正压。所以可考慮在啟動時創(chuàng)建一個后臺線程欣福,將即時性不強的初始化操作放到后臺線程。
Adapter的處理
對于Adapter是放在View好還是Presenter好焦履,這個問題確實難以解決拓劝。但在使用解耦的ViewHolder后這個問題便很明了。視圖的創(chuàng)建與改變?nèi)蒝iewHolder管理裁良。然后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訂閱發(fā)布模式在MVP中作用很大牧抵。可以極大簡化層間通訊的處理侨把。View向Presenter訂閱數(shù)據(jù)犀变。Presenter可以向Model層訂閱數(shù)據(jù)。形成一個數(shù)據(jù)鏈秋柄。數(shù)據(jù)可以直接鏈式到達View層获枝。優(yōu)雅易拓展。
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) {
//顯示數(shù)據(jù)
}
@Override
public void setError(Throwable e) {
//顯示錯誤
}
}
Beam
Beam是我做的一套基于MVP模式的快速開發(fā)框架骇笔。參考了nucleus省店。上面的示例代碼都是使用了這個(為方便復(fù)制的這個框架demo代碼.= =)嚣崭。定義了一套開發(fā)規(guī)范。并提供了基于這套規(guī)范的Activity懦傍,F(xiàn)ragment雹舀,Presenter,Model等父類及控件和API等粗俱,完成APP開發(fā)過程中大量繁瑣工作说榆。并進行了一系列優(yōu)化。詳情看這里