Android MVP模式的化簡深入理解
網上關於MVP的冗長教程已經很多了,自己結合所做的MVP專案儘量簡潔,簡單,大白話的方式記錄心得,為了日後遺忘的差不多了能迅速把記憶抓起來。一圖勝千言,先上圖。圖1是mvp的框架流程圖:
圖1
簡單介紹下MVP三劍客:Model,View, Presenter,重點會結合Demo去剖析。
Model: 它是涉及資料管理的介面,簡單的說,只要是程式碼處理資料,都會由這個Model來負責。
View: 你能看到的都是View , 作為使用者能看到手機上的介面都是View檢視層,作用僅僅是繪製UI元素和響應UI操作,比如點選UI元素。
Presenter: Presenter是三劍客的核心部分,app的邏輯程式碼基本全寫在Presenter中了,從圖1就能看出來,它承上啟下,聯絡著Model層和View層
需要注意的是,View層不和Model層直接聯絡,需要Presenter為中介,上面說的理論畢竟有些泛泛之談,結合下面的Demo繼續具體的分析。
圖2
Demo實現的效果很簡單,點選介面上的搜尋按鈕,會發送http協議獲取某個城市的經緯度,當獲取到http請求回執後,反序列化Json,然後重新繪製介面,顯示經緯度。從MVP的模式去講,這個包含搜尋Button的,點選搜尋後彈出的轉圈等待介面就是View層,當響應點選事件之後,View層就會通知Presenter層,讓Presenter去傳送獲取經緯度的http協議,並且在Presenter中監聽http協議的回執,若協議收發成功,那麼presenter就會通知View層去重新繪製UI。下面貼出具體程式碼進行理解
/**
* Created by xjc on 2018/11/26.
*/
public interface MainPresenter {
interface View extends BaseView {
//通知介面(View層)重新整理的邏輯函式
void refreshViewMistakeIntruductionList( LocationResponseBean bean);
}
interface Model {
//傳送獲取經緯度座標協議
void getLonLat();
}
}
一個Presenter是由兩部分組成的:Presenter介面和Presenter的具體實現(Impl),Presenter介面中包含了兩個interface:View和Model。 View介面的抽象方法就是聲明瞭Presenter層和View層之間的聯絡,要和View之間有怎樣的互動,比如上面View介面中的方法就是通知介面重新整理。Model介面就是MVP中Model層要實現的功能,上述程式碼Model層中抽象方法就是為了傳送經緯度的http協議。這樣一目瞭然,這個Presenter的功能有兩個,一是獲取經緯度,二是通知介面重繪,但是具體怎麼幹,怎麼一點點寫出來,都會交給這個Presenter介面的實現類。
/**
* Created by xjc on 2018/11/26.
*/
public class MainPresenterImpl extends BasePresenter<MainPresenter.View> implements MainPresenter.Model{
private ApiHttpService apiHttpService;
@Inject
public MainPresenterImpl(ApiHttpService apiHttpService) {
this.apiHttpService = apiHttpService;
}
@Override
public void getLonLat() {
JSONObject jsonObject = new JSONObject();
try {
jsonObject.put("a","大連");
} catch (JSONException e) {
e.printStackTrace();
}
//retrofit2.0傳送http請求
invoke(apiHttpService.fetchLocation(jsonObject.toString()),new Callback<LocationResponseBean>(){
@Override
public void onResponse(LocationResponseBean bean){
mView.refreshViewMistakeIntruductionList(bean);
}
});
}
}
可以看到實現類繼承並實現了presenter介面中的View和Model介面,若協議收發成功,那麼會調Presenter介面中View interface的方法,來通知介面該做一些XX操作了
mView.refreshViewMistakeIntruductionList(bean);
下面來看一下主介面(View層)
/**
* Created by xjc on 2018/11/26.
*/
public class MainActivity extends IBaseActivity<MainPresenterImpl> implements MainPresenter.View {
private Toast mToast = null;
@BindView(R.id.tv_location)
TextView tv_location;
@BindView(R.id.btn_search)
Button btn_search;
@Override
protected int getLayoutId() {
return R.layout.activity_main;
}
@Override
protected void loadData() {
}
@Override
protected void initView() {
}
@Override
protected void initInject() {
DaggerMainComponent.builder().apiHttpModule(new ApiHttpModule()).build().injectMain(this);
}
@Override
public void refreshViewMistakeIntruductionList(LocationResponseBean bean) {
//獲取到資料,取消轉圈
dismiss();
//重繪text
tv_location.setText(bean.getLat()+","+bean.getLon());
}
@OnClick(R.id.btn_search)
public void searchLocation(View view) {
//傳送http請求
mPresenter.getLonLat();
//轉圈等待
createLoading();
}
@Override
public void setState(int state) {
}
}
可以看到主介面只實現了Presenter的View介面,這就是部落格最開始的流程圖中View層不能和Model層直接建立聯絡的具體程式碼實現,當Presenter實現類的 mView.refreshViewMistakeIntruductionList(bean)被執行的時候,作為子類的MainActivity中的覆寫函式會被執行,取消轉圈並且重繪UI
@Override
public void refreshViewMistakeIntruductionList(LocationResponseBean bean) {
//獲取到資料,取消轉圈
dismiss();
//重繪text
tv_location.setText(bean.getLat()+","+bean.getLon());
}
由此,MVP的一整套流程都在這個Demo中完美的實現了,這也是我認為搭建MVP專案最簡單,最方便的寫法。Demo已打包上傳:https://download.csdn.net/download/crystal_xing/10811027,關於MVP中所用的依賴注入框架Dagger2,會用同樣的Demo再寫一篇新的部落格進行總結分析。