MVP應用架構模式

編輯於2017年3月24日

參考:《Android源碼設計模式 解析與實戰》一書


大致分包如下圖

M:負責獲取,存儲,檢索等操作數據,持有數據對象並直接對其進行操作。

V: View Interface:抽取UI及數據展示隱藏等相關操作的方法(可能多個view用到這些方法)。

    View:負責繪製、初始化UI;持有Presenter對象,view把與數據相關的業務邏輯都交給Presenter;持有沒有數據的數據對象,數據需要presenter傳遞過來;一些點擊後跳轉一類的操作仍由其負責。

P:同時持有View和Model的引用;因爲view需要把與數據相關的業務邏輯都交給Presenter,需要調用presenter,所以view是傳參(即構造方法的形參傳過來的);model沒有辦法主動從Presenter那拿回數據繼續處理,也就是model沒辦法調用Presenter,所以model是實參。Presenter通知Model處理好數據並返回,調用了model的方法;Presenter拿到數據交給view展示,調用了view的方法(即view interface的方法);Presenter把數據交給model繼續或者再次處理,調用了model的方法;上述三件事先後順序根據具體情況決定,比如先獲取數據調用model,再展示在UI上調用view,最後再存儲數據調用model。

個人觀點:MVP是View需要數據進行展示等相關操作(接口中的方法),於是便通知了presenter讓其準備好數據;presenter本身並不持有數據,於是便讓model獲取數據並傳給他,拿到數據後presenter自己並沒有使用數據(不是全局變量);他把數據直接給了view讓其去使用(是全局變量),同時把數據給了model讓其繼續處理;當view需要同樣數據時可以自身獲取,當view需要經過另外一種處理方式後的數據時便再次通知presenter。

 

MVP有很多優點,易於維護、易於測試、鬆耦合、複用性高、健壯穩定、易於拓展等。但是,由於Presenter經常性地需要執行一些耗時操作(等待Model執行完耗時操作),而Presenter持有了activity的強引用,如果在耗時操作結束前activity就被銷燬了,就會導致Presenter一直持有activity對象,使得activity對象無法被回收,此時就發生了內存泄漏。

我們可以通過弱引用和activity、fragment的生命週期來解決這個問題。首先建立一個Presenter抽象,我們命名爲BasePresenter,他是一個泛型類,泛型類型爲view角色要實現的接口類型。具體代碼如下:

 

public abstract class BasePresenter<V> {
    /**@Field: (View接口類型的弱引用) */
    protected Reference<V> mViewRef;

    /**
     * 建立關聯
     * @param view
     */
    public void attachView(V view){
        mViewRef=new WeakReference<V>(view);
    }

    /**
     * 解除關聯
     */
    public void detachView(){
        if (mViewRef!=null){
            mViewRef.clear();
            mViewRef=null;
        }
    }

    /**
     * 判斷是否與View建立了關聯
     * @return
     */
    public boolean isViewAttached(){
        return mViewRef!=null&&mViewRef.get()!=null;
    }

    /**
     * 獲取View
     * @return
     */
    protected V getView(){
        return mViewRef.get();
    }
}

 

view類型通過BasePresenter的泛型類型傳遞進去,Presenter對這個view持有弱引用。通常情況下這個view類型應該是實現了某個特定接口的activity或者fragment等類型。

創建一個BaseActivity基類,通過這個基類的生命週期函數來控制它與Presenter的關係,相關代碼如下:

 

public abstract class BaseActivity<V,P extends BasePresenter<V>> extends Activity{
    /**@Field: (與Presenter建立關係) */
    protected P mPresenter;

    /**
     * 創建Presenter
     * @return
     */
    protected abstract P createPresenter();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mPresenter=createPresenter();
        mPresenter.attachView((V)this);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mPresenter.detachView();
    }
}


同理,BaseFragment相關代碼如下:

 

 

public abstract class BaseFragment<V,P extends BasePresenter<V>> extends Fragment {
    /**@Field: (與Presenter建立關係) */
    protected P mPresenter;

    /**
     * 創建Presenter
     * @return
     */
    protected abstract P createPresenter();

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mPresenter=createPresenter();
        mPresenter.attachView((V)this);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        mPresenter.detachView();
    }
}

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章