要想搞清楚MVP是什么,先得搞清楚MVC。
MVC模式
MVC模式的結(jié)構(gòu)分為三部分组力,實(shí)體層的Model,視圖層的View抖拴,以及控制層的Controller燎字。
- View層其實(shí)就是程序的UI界面,用于向用戶展示數(shù)據(jù)以及接收用戶的輸入阿宅,類比XML視圖文件候衍;
- Model層就是數(shù)據(jù)實(shí)體及邏輯;
- Controller控制器用于更新UI界面和數(shù)據(jù)實(shí)例洒放,類比Activity蛉鹿;
MVP模式
MVP模式的核心思想:
MVP把Activity中的UI邏輯抽象成View接口,把業(yè)務(wù)邏輯抽象成Presenter接口往湿,Model類還是原來的Model妖异。
相比于MVC模式,MVP模式中的Activity工作簡單了领追,只用來響應(yīng)生命周期他膳,其他工作都丟到Presenter中去完成。從上圖可以看出绒窑,Presenter是Model和View之間的橋梁矩乐,為了讓結(jié)構(gòu)變得更加簡單,View并不能直接對Model進(jìn)行操作,這也是MVP與MVC最大的不同之處散罕。
在MVP模式里通常包含4個(gè)要素:
- View:負(fù)責(zé)繪制UI元素分歇、與用戶進(jìn)行交互(在Android中體現(xiàn)為Activity);
- View interface:需要View實(shí)現(xiàn)的接口,View通過View interface與Presenter進(jìn)行交互欧漱,降低耦合职抡,方便進(jìn)行單元測試;
- Model:負(fù)責(zé)存儲(chǔ)、檢索误甚、操縱數(shù)據(jù)(有時(shí)也實(shí)現(xiàn)一個(gè)Model interface用來降低耦合);
- Presenter:作為View與Model交互的中間紐帶缚甩,處理與用戶交互的負(fù)責(zé)邏輯。
MVP模式的好處
- 分離了視圖邏輯和業(yè)務(wù)邏輯窑邦,降低了耦合;
- Activity只處理生命周期的任務(wù)擅威,代碼變得更加簡潔
- 視圖邏輯和業(yè)務(wù)邏輯分別抽象到了View和Presenter的接口中去,提高代碼的可閱讀性
- Presenter被抽象成接口冈钦,可以有多種具體的實(shí)現(xiàn)郊丛,所以方便進(jìn)行單元測試
一般單元測試都是用來測試某些新加的業(yè)務(wù)邏輯有沒有問題,如果采用傳統(tǒng)的代碼風(fēng)格(習(xí)慣性上叫做MV模式瞧筛,少了P)厉熟,我們可能要先在Activity里寫一段測試代碼,測試完了再把測試代碼刪掉換成正式代碼较幌,這時(shí)如果發(fā)現(xiàn)業(yè)務(wù)有問題又得換回測試代碼揍瑟,咦,測試代碼已經(jīng)刪掉了乍炉!好吧重新寫吧……
MVP中绢片,由于業(yè)務(wù)邏輯都在Presenter里,我們完全可以寫一個(gè)PresenterTest的實(shí)現(xiàn)類繼承Presenter的接口岛琼,現(xiàn)在只要在Activity里把Presenter的創(chuàng)建換成PresenterTest杉畜,就能進(jìn)行單元測試了,測試完再換回來即可衷恭。萬一發(fā)現(xiàn)還得進(jìn)行測試此叠,那就再換成PresenterTest吧。
MVP的使用
工程結(jié)構(gòu)如下:
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() {
/*
* 網(wǎng)絡(luò)操作,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