要想搞清楚MVP是什么,先得搞清楚MVC。
MVC模式
MVC模式的结构分为三部分,实体层的Model,视图层的View,以及控制层的Controller。
- View层其实就是程序的UI界面,用于向用户展示数据以及接收用户的输入,类比XML视图文件;
- Model层就是数据实体及逻辑;
- Controller控制器用于更新UI界面和数据实例,类比Activity;
MVP模式
MVP模式的核心思想:
MVP把Activity中的UI逻辑抽象成View接口,把业务逻辑抽象成Presenter接口,Model类还是原来的Model。
相比于MVC模式,MVP模式中的Activity工作简单了,只用来响应生命周期,其他工作都丢到Presenter中去完成。从上图可以看出,Presenter是Model和View之间的桥梁,为了让结构变得更加简单,View并不能直接对Model进行操作,这也是MVP与MVC最大的不同之处。
在MVP模式里通常包含4个要素:
- View:负责绘制UI元素、与用户进行交互(在Android中体现为Activity);
- View interface:需要View实现的接口,View通过View interface与Presenter进行交互,降低耦合,方便进行单元测试;
- Model:负责存储、检索、操纵数据(有时也实现一个Model interface用来降低耦合);
- Presenter:作为View与Model交互的中间纽带,处理与用户交互的负责逻辑。
MVP模式的好处
- 分离了视图逻辑和业务逻辑,降低了耦合;
- Activity只处理生命周期的任务,代码变得更加简洁
- 视图逻辑和业务逻辑分别抽象到了View和Presenter的接口中去,提高代码的可阅读性
- Presenter被抽象成接口,可以有多种具体的实现,所以方便进行单元测试
一般单元测试都是用来测试某些新加的业务逻辑有没有问题,如果采用传统的代码风格(习惯性上叫做MV模式,少了P),我们可能要先在Activity里写一段测试代码,测试完了再把测试代码删掉换成正式代码,这时如果发现业务有问题又得换回测试代码,咦,测试代码已经删掉了!好吧重新写吧……
MVP中,由于业务逻辑都在Presenter里,我们完全可以写一个PresenterTest的实现类继承Presenter的接口,现在只要在Activity里把Presenter的创建换成PresenterTest,就能进行单元测试了,测试完再换回来即可。万一发现还得进行测试,那就再换成PresenterTest吧。
MVP的使用
工程结构如下:
MainContract
public interface MainContract {
interface View {
void showMovie(String movies);
}
interface Presenter {
void getMovie();
}
}
MainPresenter
public class MainPresenter implements MainContract.Presenter {
public static final String TAG = "gaode_map";
private MainContract.View mMapView;
public MainPresenter(@NonNull MainContract.View mMapView) {
this.mMapView = mMapView;
}
@Override
public void getMovie() {
/*
* 网络操作,model部分,已省略
* */
String movie = "摔跤吧爸爸";
mMapView.showMovie(movie);
}
}
MainActivity
public class MainActivity extends Activity implements MainContract.View {
MainPresenter mainPresenter;
TextView txt_movie;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
txt_movie = (TextView)findViewById(R.id.txt_movie);
mainPresenter = new MainPresenter(this);
findViewById(R.id.btn_movie).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mainPresenter.getMovie();
}
});
}
@Override
public void showMovie(String movies) {
txt_movie.setText(movies);
}
}
源码:
https://github.com/woshizmxin/Mvp