1. MVP介紹
MVP全名是Model-View-Presenter,MVP 是從經(jīng)典的模式MVC演變而來的。
Model:模型層,負(fù)責(zé)處理數(shù)據(jù)的加載或存儲。與MVP中的M一樣。
View:視圖層,負(fù)責(zé)界面數(shù)據(jù)的展示,與用戶進行交互。與MVP中的V一樣。
Presenter:負(fù)責(zé)邏輯業(yè)務(wù)的處理。跟MVC中的C有所區(qū)別。
1.1 作用
- 將Model與View徹底分離。
- 解決MVC中
Activity職責(zé)過多,代碼臃腫的問題。
1.2 流程

1.View接受用戶的請求,然后將請求傳遞給Presenter。
2.Presenter進行業(yè)務(wù)邏輯處理,修改Model。
3.Presenter通知View去更新界面顯示。
1.3 關(guān)系
通常View與Presenter是一對一的,但復(fù)雜的View可以綁定多個Presenter來處理邏輯。
2. MVP例子實現(xiàn)
還是以點擊按鈕對數(shù)字+1為例子,將其改造成MVP模式。與MVC不同的是,一般Activty會當(dāng)作View層來處理。
2.1 Model層
跟MVC不同的地方在于Model不會跟View發(fā)生交互,只會跟Presenter交互。
public class NumModel {
private int num = 0;
public void add(ModelCallback callback) {
callback.onSuccess(++num);//通知Presenter結(jié)果
}
public interface ModelCallback {//數(shù)據(jù)回調(diào)接口
void onSuccess(int num);
void onFailed(String text);
}
}
2.2 View層
MVP中Activty也充當(dāng)了View層,同時會持有Presenter的引用。
IView接口,暴露給Presenter的方法:
public interface IView {
void updateUI(String text);
}
PresenterActivity類
public class PresenterActivity extends Activity implements IView {//實現(xiàn)IView接口
private TextView mTextView;
private Button mButton;
private IPresent mPresent;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_controller);
mTextView = findViewById(R.id.tv_show);
mButton = findViewById(R.id.btn_add);
mPresent = new NumPresenter(this);//初始化一個Present
mButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mPresent.add();//交給Present去處理
}
});
}
@Override
public void updateUI(String text) {//實現(xiàn)IView接口里面的更新UI的方法
mTextView.setText(text);
}
}
activity_controller.xml,跟MVC的布局一樣:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/tv_show"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="0"/>
<Button
android:id="@+id/btn_add"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="點擊+1"/>
</LinearLayout>
2.3 Presenter層
負(fù)責(zé)業(yè)務(wù)邏輯處理。
IPresent接口,暴露給View調(diào)用:
public interface IPresent {
void add();
}
NumPresenter類,具體的邏輯處理:
public class NumPresenter implements NumModel.ModelCallback, IPresent {//實現(xiàn)ModelCallback,IPresent等接口
private NumModel mNumModel;
private IView mView;
public NumPresenter(IView view) {
mView = view;//持有IView對象
mNumModel = new NumModel();//創(chuàng)建NumModel對象
}
public void add() {//IPresent接口的方法,來自View層的調(diào)用
mNumModel.add(this);//相關(guān)邏輯處理,這里直接交給Model層
}
@Override
public void onSuccess(int num) {//ModelCallback接口的方法,來自Model層的成功回調(diào)
mView.updateUI(num + "");//通知View層更新UI
}
@Override
public void onFailed(String text) {//ModelCallback接口的方法,來自Model層的失敗回調(diào)
mView.updateUI("失敗");//通知View層更新UI
}
}
3. MVC與MVP區(qū)別
- 最主要的區(qū)別就是MVP中View與Model并不直接交互,而在MVC中View可以與Model直接交互。
4. MVP的優(yōu)點
- View與Model完全分離,我們可以修改視圖而不影響模型。
- 可以更高效地使用模型,因為所有的交互都發(fā)生Presenter中。
- Presenter與View的交互是通過接口來進行的,有利于添加單元測試。
5. 存在的問題
- 頁面邏輯復(fù)雜的話,相應(yīng)的接口也會變多,增加維護成本??梢远x一些基類去分離一些公共的邏輯。
- 系統(tǒng)內(nèi)存不足時,系統(tǒng)會回收Activity。一般我們都是用OnSaveInstanceState()去保存狀態(tài),用OnRestoreInstanceState()去恢復(fù)狀態(tài)。但是在我們的MVP中,View層是不應(yīng)該去直接操作Model的,所以這樣做不合理,同時也增大了M與V的耦合。解決辦法是不要將Activity作為View層,可以把Activity當(dāng)Presenter來處理。具體實現(xiàn)這里就不分析了,有興趣的可以研究一下。
- UI改變的話,比如TextView 替換 EditText,可能導(dǎo)致Presente的一些更新UI的接口也跟著需要更改,存在一定的耦合。
6.其他
- MVP在實現(xiàn)上來說可以有多種思路,不同的實現(xiàn)方式其優(yōu)缺點也是不同的,具體問題具體分析。
- 實際上MVP還有很多東西可以發(fā)掘的,鑒于能力和時間有限,這里就不深入研究了。后面有新的體會的話也會繼續(xù)更新的。
貼篇MVP詳細介紹的文章:Android MVP 詳解
相關(guān)文章閱讀
Android框架模式——MVC
Android框架模式——MVP
Android框架模式——MVVM