Android學習筆記MVP模式框架

Android學習筆記MVP模式框架

1.MVP模式介紹:
在上一次學習中,我簡單的介紹了MVC構架,這次我來簡單的介紹下什麼是MVP。對於MVP,他其實就是MVC的一個演化版本,MVP全稱Model View Presenter。目前MVP在android應用開發中越來越重要了,相信不少的開發者也在各種討論關於MVP的理論了。那麼這個MVP模式他到底有哪些應用的好處呢?首先MVP能夠有效的降低View的複雜性,避免業務邏輯被塞進View中,使得View代碼優化了不少。MVP模式會解除View與Model的耦合,同時又帶來了良好的可擴展性、可測試性,保證了系統的整潔性、靈活性。可能對於簡單的應用,你會覺得MVP會稍微顯得有點麻煩,因爲他提出了各種各樣的接口概念,是的整個應用充斥着零散的接口,但是對於比較複雜的應用來說,MVP模式是一種良好的構架模式,它能夠非常好的組織應用結構,使得應用變得靈活
 
 
2. MVP簡單結構圖:

這裏寫圖片描述

從上圖可以看出,MVP模式很好的分離顯示層和邏輯層,他們之間通過接口進行通信,降低耦合。理想化的MVP模式可以實現同一份邏輯代碼搭配不同的顯示界面,因爲他們之間並不依賴於具體,而是依賴與抽象。這使得Presenter可以運用於任何實現了View邏輯接口的UI,使之具有更廣泛的使用性,保證了靈活度。
 
3. MVP模式的三個角色:

3.1 Presenter——交互中間人

Presenter主要作爲溝通View和Model的橋樑,它從Model層檢索數據後,返回給View層,是的View
和Model直接沒有耦合,也將業務邏輯從View角色上抽離出來,相比MVC模式,就很好的減少了View
中的邏輯實現代碼。

 
3.2 View——用戶界面

View通常是指Activity、Fragment或者某個View控件,它含有一個Presenter成員變量。通常View需要
實現一個邏輯接口,將View上的操作通過會轉交給Presenter進行實現,最後,Presenter調用View邏輯
接口將結果返回給View元素。
 
 

3.3 Model——數據的存儲

對於一個結構化的App來說,Model角色主要是提供數據的存取功能。Presenter需要通過Model層存
儲、獲取數據,Model就像一個數據倉庫。更直白地說,Model是封裝了數據庫Dao或者網絡獲取數據的
角色,或者兩種數據獲取方式的集合。

 
4. MVP的代碼實現:

關於具體的實現我就不在這裏重複寫了,有想了解的大家可以參考我的這些MVP模式框架的代碼:

Android-緩存網絡圖片(MVP模式)學習筆記

Android之SqliteDatabase(MVP模式)實現用戶登錄註冊功能

Android MVP模式 解析JSON 顯示到ListView上

 
5. 關於MVP與Activity、Fragment的生命週期:

綜合上面的代碼,我們可以很清除的知道,MVP有很多有點,例如易於維護、易於測試、鬆耦合、複用性高、健壯穩定、易於擴展,但是,由於Presenter經常性地執行一些耗時操作,例如,我們上述的緩存網絡請求網絡圖片。由於Presenter持有了MainActity的強引用,如果在請求結束之前Activity被銷燬了,那麼由於網絡請求還沒有返回,導致Presenter一直持有MainActivity對象,是的MainActivity對象無法被回收,此時就會發生內存泄露。那麼對於這種問題如何解決呢?答案是可以通過弱引用和Activity、Fragment的生命週期來解決這個問題。首先建立一個Presenter抽象類,我們把它命名爲BaseAdapter,他是一個泛型類,泛型類類型爲View角色要實現的接口類型。具體代碼如下。

BasePresenter.java

public class BasePresenter<V extends ViewInter> {

    protected WeakReference<V> weakReference;//View接口類型的弱引用

    public void attach(V t){
        weakReference = new WeakReference<>(t);//每次將需要關聯的View接口類型的類與其建立聯繫
    }

    public void deAttach(){//如果Activity、Fragment等View控件銷燬時調用該方法,解除他們之間的關聯
        if(weakReference != null){
            weakReference.clear();
            weakReference = null;
        }
    }
    public boolean isViewAttached(){
        return weakReference != null && weakReference.get() != null;
    }
    public V getView(){
        if(weakReference != null){
            return weakReference.get();
        }
        return  null;
    }

以上的四個方法,分別是建立關聯、解除關聯、判斷是否與View建立了關聯、獲取View。View類型通過Presenter的泛型類型傳遞過來,Presenter對這個View持有弱引用。通常情況下這個View類型應該是實現了某個特定接口的Activity或者Fragment等類型。接下來還需要創建一個BaseActivity基類,通過這個基類的生命週期方法來控制它與Presenter的關係。相關代碼如下。

BaseActivity.java

public abstract class BaseActivity<V extends ViewInter,T extends BasePresenter> extends AppCompatActivity {

    protected T basePresenter;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        basePresenter = getBasePresenter();
        basePresenter.attach((V)this);
    }

    public abstract T getBasePresenter();

    @Override
    protected void onDestroy() {
        basePresenter.deAttach();
        super.onDestroy();
    }
}

BaseActivity含有兩個泛型參數,第一個是View接口類型,第二個是Presenter的具體類型。通過泛型參數,使得一些通用的邏輯可以被抽象到BaseActivity類中。下面看看具體要使用的MainActivity類的實現。

MainActivity.java

//主界面啓動,展示數據等。
public class MainActivity extends BaseActivity<MainActivity,Presenter> implements ViewInter<Bean.NewslistBean> {

    private String path = "http://apis.baidu.com/txapi/mvtp/meinv?num=10";
    private GridView mGrid;
    private MyAdapter adapter;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        init();
        basePresenter.load(path);
    }

    private void init() {
        mGrid = (GridView) findViewById(R.id.mGrid);
    }

    @Override
    public Presenter getBasePresenter() {
        return new Presenter();
    }

    private void showListData(List<Bean.NewslistBean> data) {
        if (adapter == null) {
            adapter = new MyAdapter(data, R.layout.list_item);
            mGrid.setAdapter(adapter);
        } else {

        }
    }
    //通過presenter代理類爲我們提供數據
    @Override
    public void getAdapterData(List<Bean.NewslistBean> data) {
        showListData(data);
    }
}

通過上面的代碼,大家可以看出,在BaseActivity中的onCreate方法中,會通過getBasePresenter方法創建一個具體的Presenter,這個Presenter的類型就是BasePresenter類型。構建Presenter之後調用attach方法與Activity建立關聯。而在onDestory方法中,則會與Activity解除關聯,從而避免內存泄露。有些人可能會問,如果在onDestory中解除了對Activity的引用,那麼就沒有必要再用弱引用了。對於這個問題的答案是,並不是在任何情況下Activity的onDestroy都會被調用,一旦這種情況發生,弱引用也能夠保證不會造成內存泄露。而通過BaseActivity的封裝維護Presenter與View關聯關係的代碼,使得子類可以避免重複的代碼,上面的代碼正是如此。Presenter的創建以及View建立關聯等操作都被封裝到BaseActivity中,消除了子類重複代碼的同時又避免了Activity的內存泄露問題。所以,在以後的設計中,你都可以爲Activity、Fragment等類型都建立一個類似這樣的基類,這樣一來你就可以將這種思想運用到更廣闊的範圍了。

最後,從整體效果來說,MVP是開發過程中非常值得推薦的構架模式,他能夠將各組件進行解偶,並且帶來了良好的擴展性、可測試性、穩定性、可維護性,同時使得每個類型的職責相對單一、簡單,便面了大量的“胖”程序存在,例如數千行的Activity類。他有效的業務邏輯、數據處理等工作從Activity等View元素中抽離出來,使得每個類儘可能簡單,同時每個模塊能夠獨立進行演化。它的思想也非常好的體現了面向對象的設計原則。

發佈了58 篇原創文章 · 獲贊 19 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章