安卓MVP淺析及Presenter的生命週期問題

jlanglang發表於2018-01-18

現在來說,mvp不算是個新鮮的東西了,很多了都開始練手或者已經用到專案去了

對於mvvm,databinding框架,用了下,發現很多問題,程式碼寫起來也不友好,暫時不考慮

m :  model 模型.

很多人理解成bean物件,我覺得不全是, 用獲取資料比較貼切.

在以前寫mvc的時候,我習慣抽成initData()來表示modle.

public interface  Model {

      Bean load(String url,params)

}

安卓MVP淺析及Presenter的生命週期問題

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的單個或多個操作.

結構圖:


安卓MVP淺析及Presenter的生命週期問題


總結:

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反而顯得繁瑣了.


寫個文章做個筆記,哈哈.

相關文章