現在來說,mvp不算是個新鮮的東西了,很多了都開始練手或者已經用到專案去了
對於mvvm,databinding框架,用了下,發現很多問題,程式碼寫起來也不友好,暫時不考慮
m : model 模型.
很多人理解成bean物件,我覺得不全是, 用獲取資料比較貼切.
在以前寫mvc的時候,我習慣抽成initData()來表示modle.
public interface Model {
Bean load(String url,params)
}
modle,我推薦用retrofit2+rxjava來寫,完全適用啊,對比一看,是不是感覺幾乎沒區別?
傳送門:retrofit2+rxjava
v:view檢視
在mvp中,有人把activity/fragment理解成presenter,
我覺得還是理解成v好一點,
比較糾結是,activity有生命週期,怎麼就是單純的v呢.
但如果理解成presenter的話,那麼和mvc區別就不大了吧.
具體使用:
1.寫一個view介面
public interface View {
//抽取相對的activity裡面的各種行為
//如:
void show();
void bindData(Bean b);
}
2,activity實現這個設計好的view介面
public class MainActivity extends Activity implements View{
Presenter presenter;
@Override
protected voidonCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
presenter = new Presenter(this);
}
public void show(){
}
public void bindData(Bean b){
........
//等待資料,設定view.
}
}
3,實現每個行為的邏輯:對某個控制元件做什麼事.
public void show(){
//具體操作.比如彈個toast啥的,設定某個控制元件啥的
}
4.持有presenter
這裡有點難理解,持有presenter是什麼意思?
我們不管做什麼操作,都是一次事件
而這個事件由誰接收,當然是activity接收了.
如果activity不持有presenter,怎麼告訴presenter,我需要獲得資料.
對於view的功能設計
想好這個介面有哪些操作了.這個也不是很難,
拿著效果圖,分析一下就出來了,
比如textview設定個內容啊,點選事件啊,選中啊,button彈出對話方塊啊
就拿TextView來說吧,Textview這個控制元件是不是有settext(),setColor().setTextsize().....方法.
在mvp模式裡面,我們把activity理解成View,假設Activity裡面有settext(),setColor().setTextsize()方法
我們寫這個view介面就相當於把這些方法從Activity抽取出來,
這個介面和Activity寫好了一般是不需要改的,除非介面大改.那沒辦法,只能兩邊一起改了
因為xml都改了,控制元件啥的都改了,對應的Activity和view介面能不改麼.
不過由於分離開了,改起來也簡單.因為沒有邏輯操作.
p:控制 presenter
一般寫法:
public interface Presenter {
void loadData();
}
public interface PresenterImpl implements Presenter {
View v;
public PresenterImpl(View v){
this.v = v;
}
publc void loadData(){
Modler modle = new Modle();//建立modle
Bean bean = modle.load("url",params);//獲得資料
v.bindData(bean);//資料繫結view
}
}
既然view關心本身有哪些行為,那麼p就是控制view了
通過事件觸發,presenter去連線model獲得資料,然後將model與view繫結,
也可以只是呼叫view的單個或多個操作.
結構圖:
總結:
presenter和view相互持有呼叫,presenter可以同時操作Modle和View,但是Modle和View之間不能呼叫.
mvc的糾結的地方就是,其實只有mv,沒有c,因為c和v是幾乎是一個東西,activity/fragment嘛.
很多時候除了bean,mvc其實整個都在Activity裡面- -
Presenter生命週期
這個問題很揪心,我想很多人懵逼的地方就在這
舉個例子:
Presenter控制邏輯,也就是控制網路操作,繫結資料,一系列邏輯都在這.
那麼,當activity關閉以後,Presenter怎麼處理網路請求,非同步操作呢?
比如上面的loadData(),如果acitivity已經關閉了,而網路操作又沒走完.
就會記憶體洩漏.會不會空指標不好說.
view雖然持有p,但是也不能在Activity的onDestroy裡面直接的將p=null吧
物件=null也只是斷開引用而已,還並不是真的釋放.
這樣沒用的,而且p還持有view呢,非同步也不會因此結束,
所以得有個介面告訴p,我要掛了,你也自殺吧.
所以:
interface BasePresenter {
void onStart();
void onDestroy();
}
讓所有的Presenter都繼承BasePresenter,然後在activity中相應的生命週期裡面呼叫
在相應的方法裡面,初始化,結束非同步操作,釋放資源,將view=null;
而在activity裡面,由於Presenter並沒有view的引用了,
所以p隨著activity的銷燬也就跟著銷燬了.不會造成上下文的洩漏等.
mvp的優點:
1.真正用起來,會發現模組很清晰,
2.解耦,模組清晰,耦合度自然就低了,但是耦合度低不代表改起來就很方便,哈哈
需求改動大的話,其實改起來還是麻煩,不過比起在上千行的activity裡面改程式碼,還是舒服很多的,
比較推薦的寫法:
public class Contract {
public interface View {
void show();
void bindData();
}
public interface Presenter extends BasePresenter{
void loadData();
}
public interface Model {
void load(String url,params)
}
用一個Contract集中對應acitivity的所有mvp用到的介面,
所有功能一目瞭然,改起來也方便.
如果改需求,肯定先改介面,再去改實現類嘛.
android studio 已經有mvpHelper外掛,可以很方便生成的mvp的介面類以及實現類.
mvp的缺點:
類會非常多,每一個acitivity或者fragment要對應1個或者多個Presenter,真的很多
小專案費力,有時不如mvc方便,介面如果非常簡單,用mvp反而顯得繁瑣了.
寫個文章做個筆記,哈哈.