簡化版Android MVP

看過mvp結構的人都知道,在官方版本的mvp里面有很多大量的接口定義,沒錯 就是接口,沒次都要寫大量的接口,時間久了會覺得很煩,這里簡化了一個mvp的標準寫法少了很多接口定義,至少我現在項目中正在這么使用,不過這個MVP目前還有一層沒有挖掘,那就是M層,不過在看了[架構向] 談Android中DTO -> VO的重要性文章以后,感覺可以用在現在的M層中,做DTO,這樣讓P層在拿到數據以后只專心處理邏輯,而不用判斷太多的數據校驗。

先來看看傳統的MVP的結構走向圖:

MVP

這次的簡化來源于經過實踐發現,大部分Presenter------>View的都只是鋪鋪數據,而本著一個View擁有一個Presenter的原則,所以簡化過后的結構走向還是原來的結構走向,只是少了一點接口而已,也算的上是對MVP的一種簡化的封裝。
首先我們先來看看BasePresenter類:

public abstract class BasePresenter<T extends BaseView> {

    private WeakReference<T> weakReference;

    public BasePresenter(T baseView) {
        setView(baseView);
    }

    public T getView() {
        return weakReference!=null?weakReference.get():null;
    }

    public void setView(T view) {
        this.weakReference = new WeakReference<>(view);
    }

    public void recycle(){
        if(weakReference!=null){
            weakReference.clear();
            weakReference=null;
        }
    }
}

所有的Presenter都需要繼承這個BasePresenter,更具結構類圖,此類中需要依賴一個視圖層的接口,因此在繼承此類的時候通過泛型看到需要傳入一個繼承自BaseView接口的接口。沒錯Presenter層在向View通信的時候任然是需要依靠接口來通信的,這里取消了Presneter和Model的接口依賴關。從大部分實踐上來看,感覺這兩曾的的依賴關系并不是很重要,所以取消掉了,當然也有可能是我還沒發現P與M之間的依賴好處。如果您有不同的看法可以在評論區留言,大家共同學習互相借鑒。在這里,M層只是一個簡單的JavaBean。當然如果加上本文開頭說的DTO,M曾的意義就體現出來了,不過目前還沒有這么做。
在BasePresenter抽象類中,我們還看到了一個recycle()方法,這個方法是用來清楚View的依賴。因為很多時候Presenter中處理的都是異步耗時操作,如果此時用戶等不耐煩了,推出了當然的界面,那么就很有可能會造成泄漏且如果您使用的是butterknife這個框架的話,揮發這個框架也會提共一個unbind()方法,如果這里不清楚View的依賴的話,當用戶退出界面就會發生NullPointException的異常。所以BasePresenter中提供了這個方法。繼承之后通過使用getView方法獲取依賴的view,注意 使用前需要判斷非空。

現在來看看BaseView接口:

public interface BaseView {

    void dialogShow(String message);
    void dialogShow();
    void dialogDissmiss();
}

這個接口很簡單僅僅只是一個基類,定義了一些公共的方法如這里dialog的顯示與關閉。
由于大部分View層都只是鋪數據,區別只是數據的類型不一樣,因此這里還提供幾個普通的BaseView接口,
處理一種數據的接口

public interface BaseView1<T> extends BaseView{

    void getData(T data);
}

處理兩種數據類型的接口:

public interface BaseView2<T,J> extends BaseView{

    void getData(T data);
    void getData2(J data);
}

等等。這只是偶爾用用的,因為我這里出現的平率比較多所以才加上這寫接口的。其實只需要一個BaseView接口就好了,在定義View層接口的時候基礎BaseView就行。

這里有一個使用的例子,一般項目都會有一個BaseActivity之類的東西。

public class BaseActivity<T extends BasePersent<? extends BaseView>> extends AppCompatActivity implements BaseView {
    public static String TAG;

    private T presenter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        TAG=getClass().getCanonicalName();
    }

    @Override
    protected void onDestroy() {
        if(presenter!=null){
            presenter.recycle();
        }
        super.onDestroy();
    }

    public T getPresenter() {
        return presenter;
    }

    public void setPresenter(T presenter) {
        this.presenter = presenter;
    }

    @Override
    public void showLoading(String message) {
        Log.i(TAG,"dialog show "+message);
    }

    @Override
    public void hideLoading() {
        Log.i(TAG,"dialog hiden");
    }
}

這里BaseActivity實現了BaseView接口,并實現了里面的公共方法(這里是dialog的顯示與關閉)。在onDestory()方法中,現調用了presenter中的recycle()方法來釋放引用,這樣不管presenter中做了什么耗時操作只要在getView之前判斷了非空,就避免了泄漏的風險,已經空指針異常的風險了。

在來看看我們View所依賴的Presenter

public class DemoPersent extends BasePersent<DemoPersent.DemoView> {

    Service service;

    public DemoPersent(DemoView baseView) {
        super(baseView);
        service=ZillApi.NormalAdapter.create(Service.class);
    }

    public void doOnClick(String classId){
        getView().showLoading("正在加載");
        //做了一部分的耗時操作
        service.getMainDate(classId, new CallBack() {
            @Override
            public void success(String str) {
                 //取消Dialog
                if(getView()!=null){
                    getView().hideLoading();
                }
                //處理一些數據.......
                //返回數據
                if(getView()!=null){
                    getView().updateBtn2(str);;
                }
            }
        });

    }
    public void  doSomthing(){
        String str="haha22222";
        getView().updateBtn1(str);
    }

  //Presener所以來的View
    public interface DemoView extends BaseView {

         void updateBtn1(String str);

         void updateBtn2(String str);
    }
}

下面看看具體的Activity

public class MainActivity extends BaseActivity<DemoPresenter> implements DemoPresenter.DemoView {

    TextView btn,btn1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //指定當前Activity需要的Presneter
        setPresenter(new DemoPresenter(this));

        btn= (TextView) findViewById(R.id.btn);
        btn1= (TextView) findViewById(R.id.btn1);
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                getPresenter().doOnClick("dsadas");
            }
        });

        btn1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                getPresenter().doSomthing();
            }
        });

    }

    @Override
    public void updateBtn1(String str) {
        btn.setText(str);
    }

    @Override
    public void updateBtn2(String str) {
        btn1.setText(str);
    }
}

如此在也不要擔心泄漏的風險和空指針的問題了。還少些了很多接口,代碼也簡潔多了。在View值會看到很多傻瓜式的鋪數據的過程。
在此結構的基礎上,還可以引入DataBind以及本文開頭說的DTO等進行進一步的簡化。Model層還有很大的提升空間。

歡迎共同探討更多安卓,java,c/c++相關技術QQ群:392154157
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 作者:李旺成 時間:2016年4月3日 “Android MVP 詳解(下)”已經發布,歡迎大家提建議。 MVP ...
    diygreen閱讀 128,996評論 86 1,321
  • 人笨學的慢啊。。抓緊學習MVP 網上MVP的學習資料也是多如牛毛,來看看谷歌爸爸是怎么教我們MVP的吧 項目介紹 ...
    hongjay閱讀 2,709評論 1 21
  • http://tmi.yokogawa.com/cn/industries/industrial-consumer...
    dyg540閱讀 153評論 0 0
  • 浩途最初吸引我的地方是看到了她的目的:培養一個,幸福一家,服務一群,帶動一個地區,引領更多的人走上助人自助的成長之...
    凈妍閱讀 268評論 0 4
  • 蔡小名在走廊碰到經常給他換藥的護士X20,她正好要下班,提議陪蔡小名走一段。 X20推著一輛獨輪自行車,一直低著頭...
    echo_1c53閱讀 128評論 0 0