1. 程式人生 > >Android架構:2018 主流大廠MVP模式是怎樣?

Android架構:2018 主流大廠MVP模式是怎樣?

1.前言

  • MVP 模式是目前運用最多的一種開發模式,Presenter作為Model與View的橋樑,負責業務邏輯、操作資料等工作。這樣把model與view實現了 分離(解耦合) ,有利於 結構變得更簡單 ,以便開發者更 容易管理與維護 自身的程式碼。
  • 雖然MVP具備那麼多優點,但是它不是萬能的,同樣存在一些 缺點
  • 今天為大家分析一下主流大廠是如何解決這些缺點。
  • 本文特點:圖片多,字型少
  • 文章中例項 linhaojian的Github

2.目錄

示意圖


3.MVP模式

3.1 介紹

  • MVP
    是從經典的模式MVC演變而來,它們的基本思想有相通的地方:Controller/Presenter負責邏輯的處理Model提供資料View負責顯示
    在這裡插入圖片描述

3.2 作用

  • 將 View 與 Model 分離,方便擴充套件與維護。
  • 方便 Presenter 進行單元測試。

4.MVP缺點與解決

4.1 缺點

示意圖

4.2 解決

  • 4.2.1 記憶體洩漏:

1)在Presenter傳入View例項引用時,通過 弱引用 進行封裝。
2)在Presenter中提供 繫結(attach)解綁(detach) 函式,以便呼叫者可以管理記憶體釋放。

/**
 * 將傳入的View介面例項,通過弱引用(WeakReference)把Presenter與View進行繫結。
 * @param aview  介面更新介面例項
 */
public void attach(Aview aview){
    aviewWeakReference = new WeakReference<>(aview);
}

/**
 *  將Presenter與View進行解綁,並釋放記憶體
 */
public void detach(){
    if(aviewWeakReference!=null){
        aviewWeakReference.
clear(); aviewWeakReference = null; } }
  • 4.2.2 每一個Presenter都需要編寫相同 繫結、解綁 的程式碼:

編寫一個BasePresenter類,封裝 繫結、解綁的方法。

public class BasePresenter<V> {
    private WeakReference weakReference;

    /**
     * 將傳入的View介面例項,通過弱引用(WeakReference)把Presenter與View進行繫結。
     * @param v  介面更新介面例項
     */
    public void attach(V v){
        weakReference = new WeakReference<>(v);
    }

    /**
     *  將Presenter與View進行解綁,並釋放記憶體
     */
    public void detach(){
        if(weakReference!=null){
            weakReference.clear();
            weakReference = null;
        }
    }
}
  • 4.2.3 每一個Activity都需要 初始化 Presenter與呼叫其 繫結、解綁 的方法:

編寫一個BaseActivity類,向子類提供Presenter初始化的抽象函式;並在BaseActivity中onCreate()與onDestory中呼叫對應Presenter類的attach()與detach()方法。(**提示:**Fragment同理。)

/**
 * BaseActivty:封裝Presenter的繫結與解綁方法,減少相同冗餘程式碼
 * @param <V> View介面
 * @param <P> Presenter
 */
public abstract class BaseAcitvity<V, P extends BasePresenter<V>> extends AppCompatActivity {
    private P presenter;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        presenter = createPresenter();
        if(presenter!=null){
            presenter.attach((V) this);
        }
    }

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

    /**
     * 建立繼承於BasePresenter的子類
     * @return
     */
    protected abstract P createPresenter();
}
  • 4.2.4 Model都是以非同步操作為主,因此可能按需編寫多個不同功能的資料回撥介面:

通過一些第三方的庫來處理該問題。
釋出事件/訂閱的框架:EventBusRxBusRxjava:不一樣的詮釋
萬能介面庫:Omnipotent

  • 4.2.5 Presenter與View之間的耦合度高:

舉個例子:我們app中很多介面都使用了同一個Presenter,突然收到一個需求,需要修改該Presenter的建構函式,那不是要每一個介面我都去修改一下程式碼,多浪費時間。通過 Dagger2(依賴注入庫) ,它會幫助你完成new的工作。

  • 4.2.6 一個View對應多個Presenter

有時候有些介面是存在業務功能相同的情況(例如:請求的資料一樣),這時候就需要複用Presenter。
在BasePresenter新增一個列表管理需要複用的Presenter物件。

public class BasePresenter<V> {
    private WeakReference weakReference;
    private WeakReference<HashMap<String,BasePresenter>> weakReferenceListPresenter;

    public BasePresenter(){
        weakReferenceListPresenter = new WeakReference(new HashMap<>());
    }

    /**
     * 將傳入的View介面例項,通過弱引用(WeakReference)把Presenter與View進行繫結。
     * @param v  介面更新介面例項
     */
    public void attach(V v){
        weakReference = new WeakReference<>(v);
    }

    /**
     *  將Presenter與View進行解綁,並釋放記憶體
     */
    public void detach(){
        detachPresenter();
        if(weakReference!=null){
            weakReference.clear();
            weakReference = null;
        }
    }

    /**
     * 新增複用的Presenter例項,並將View與它們進行繫結
     * @param c
     * @param p
     * @param <P>
     */
    public <P extends BasePresenter> void addPresenter(Class<P> c,P p){
        if(weakReferenceListPresenter!=null){
            (weakReferenceListPresenter.get()).put(c.getName(),p);
            p.attach(weakReference.get());
        }
    }

    /**
     *  通過類獲取對應的Presenter物件
     * @param c
     * @param <P>
     * @return
     */
    public <P extends BasePresenter> P getPresenter(Class<P> c){
        if(weakReferenceListPresenter!=null){
            return (P) (weakReferenceListPresenter.get()).get(c.getName());
        }
        return null;
    }

    /**
     * View與其他Presenter進行解綁
     */
    private void detachPresenter(){
        if(weakReferenceListPresenter!=null){
            HashMap<String,BasePresenter> map = weakReferenceListPresenter.get();
            if(map!=null){
                for(String name : map.keySet()){
                    map.get(name).detach();
                }
            }
        }
    }

5.總結

  • 4.2.4~4.2.5 中可以發現,中間者 可以解決重複編寫資料回撥介面、耦合 的問題。
  • 到此,MVP設計模式就分析完畢,希望能在開發過程中幫助大家。
  • 如果喜歡我的分享,可以點選 關注 或者 ,你們支援是我分享的最大動力 。
  • linhaojian的Github

歡迎關注linhaojian_CSDN部落格或者linhaojian_簡書

不定期分享關於安卓開發的乾貨。


寫技術文章初心

  • 技術知識積累
  • 技術知識鞏固
  • 技術知識分享
  • 技術知識交流