一、前言
MVP 跟 MVC 很相像,上一篇文章开头列出了很多种 MVC 的设计图,所以根据 MVC 的发展来看,我们把 MVP 当成 MVC 来看也不为过,因为 MVP 也是三层,唯一的差别是 Model 和 View 之间不进行通讯,都是通过 Presenter 完成。
二、MVP 详解
在介绍 MVC 的时候提到了算是致命缺点吧:在 Android 中由于 activity(god object)的存在,Controller 和 View 很难做到完全解耦,但在 MVP 中就可以很好的解决这个问题,看下 MVP 的设计图:
一般情况下就这两种。依然延续 MVC 的例子,修改下结构通过 MVP 去实现,先看下项目代码结构:
callback、http 包下内容基本一致,主要看下不同的地方:
public interface BasePresenter {
void onDestroy();
}
BasePresenter 类似于 MVC 中的 BaseModel,主要负责业务逻辑的实现。我们这里没有把业务逻辑放在 Model 里去实现,当然把主要业务逻辑放在 Model 中去实现也是可以的。google 官方的 MVP 实现方案是把业务逻辑放在 presenter 中,弱化Model,我们这里也是这样做的。
public interface BaseView<P extends BasePresenter> {
void setPresenter(P presenter);
}
BaseView 是所有 View 的父类,将 Android 中的 view 抽象化出来,只有跟 view 相关的操作都由 BaseView 的实现类去完成。
public class SampleContract {
public static class Presenter implements BasePresenter
{
public void getUserInfo(String uid,Callback1<SampleModel.UserInfo> callback)
{
SampleModel.UserInfo userInfo= new HttpUtil<SampleModel.UserInfo>().get(uid);
callback.onCallBack(userInfo);
}
@Override
public void onDestroy() {
}
}
public interface View extends BaseView<Presenter>
{
void setDataToView(SampleModel.UserInfo userInfo);
}
}
Contract 契约类这是 Google MVP sample 与其他实现方式的又一个不同,契约类用于定义同一个界面的 view 的接口和 presenter 的具体实现。好处是通过规范的方法命名和注释可以清晰的看到整个页面的逻辑。
public class SampleActivity extends AppCompatActivity implements SampleContract.View{
private SampleContract.Presenter mPresenter;
Button button;
EditText textView;
TextView tvAge,tvName;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sample);
setPresenter(new SampleContract.Presenter());
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mPresenter.getUserInfo(textView.getText().toString(), new Callback1<SampleModel.UserInfo>() {
@Override
public void onCallBack(SampleModel.UserInfo userInfo) {
setDataToView(userInfo);
}
});
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
mPresenter.onDestroy();
}
@Override
public void setDataToView(SampleModel.UserInfo userInfo) {
tvAge.setText(userInfo.getAge());
tvName.setText(userInfo.getName());
}
@Override
public void setPresenter(SampleContract.Presenter presenter) {
mPresenter=presenter;
}
}
这里的 SampleActivity 实现了 SampleContract.View 只是作为 View 存在的。虽然看起来,跟 MVC 中的实现很相似,但却有本质的区别。mPresenter 为 Model 和 View 之间交互的桥梁。Presenter 跟 View 相互持有,这里 SampleActivity 实现了 SampleContract.View,mPresenter 作为 SampleActivity 的成员变量,SampleActivity 当然持有 mPresenter,由于 mPresenter 是非静态的成员标量,因此默认持有 SampleActivity 的引用。
MVP 总结:通过引入接口 BaseView,让相应的视图组件如 Activity,Fragment 去实现 BaseView,实现了视图层的独立,通过中间层 Preseter 实现了 Model 和 View 的完全解耦。MVP 彻底解决了 MVC 中 View 和 Controller 傻傻分不清楚的问题,但是随着业务逻辑的增加,一个页面可能会非常复杂,UI 的改变是非常多,会有非常多的 case,这样就会造成 View 的接口会很庞大。
另外推荐大家阅读:Android:聊聊我所理解的MVP