動態代理在MVP中的使用

MVP在Android項目開發中是一種很常用的架構,本文不對MVP的基礎概念和基本使用進行敘述,本文要探討的問題是動態代理在MVP中的應用。

在MVP架構中,P層會持有View,在P層處理完數據後會調用View的方法更新UI。如果View頁面關閉了而P中的邏輯還沒有執行結束,那麼View頁面就會出現內存泄漏,不能被GC正常回收,所以在調用View的onCreate方法時會創建Presenter對象並建立二者的綁定關係(爲P層的View引用賦值爲當前View對象),當調用View的onDestory方法時會解除二者的綁定關係(將P層中的View引用置空),這樣纔不會導致View內存泄漏。

按照上述邏輯,在View關閉並銷燬的時候會將P層中的View引用置空,如果之後P層處理完數據又去調用View的方法,這個時候是會出現空指針異常的,那麼就需要在P層中所有調用View方法的地方判斷一下View是否爲空,這樣當需要判斷的地方很多的時候,就會感覺很麻煩,並且不容易維護,動態代理就是爲了解決這樣的問題而引入的,思路就是通過動態代理進行切面攔截來實現統一判空。

下面是在Presenter基類中對以上邏輯進行處理的代碼:

package com.znh.commonlib.base;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * Created by znh on 2019/6/3
 * <p>
 * Presenter基類
 */
public class BasePresenter<V extends IBaseView> {

    //實現了IBaseView接口的View及其代理View
    private V mView, mProxyView;

    /**
     * 綁定View
     *
     * @param view
     */
    public void attachView(V view) {
        this.mView = view;
        mProxyView = (V) Proxy.newProxyInstance(view.getClass().getClassLoader(), view.getClass().getInterfaces(), new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                if (mView == null) {
                    return null;
                }
                return method.invoke(mView, args);
            }
        });
    }

    /**
     * 解綁View
     */
    public void detachView() {
        mView = null;
    }

    /**
     * 對外提供View對象
     *
     * @return
     */
    public V getView() {
        return mProxyView;
    }
}

上述代碼中attachView方法是綁定View,在該方法中會爲mView賦值,並以mView實現的接口IBaseView爲基礎創建對應的代理對象。detachView方法是解除綁定View,在該方法中會將mView置空,這樣View就不被P層引用了。getView爲P層調用View方法提供調用對象,只不過這個調用對象不是真實的View而是代理對象,將對View的調用轉嫁到對代理對象的方法調用上,然後在代理對象的方法執行invoke時,在進行判斷真實的View是否爲空,從而來確定是否執行真實View的方法調用邏輯。

mProxyView是IBaseView接口的一個代理對象,這個對象只具備View層接口定義的所有方法能力,但是這個對象是獨立的,它沒有View的生命週期和其他內容,所以在P層對View進行解綁的時候,只需要將真實View置空即可,這個代理對象不需要置空也不會造成View內存泄漏(因爲這就是一個普通的對象),當需要調用真實View的方法更新UI時,可以替換爲調用代理對象mProxyView相對應的方法,然後在代理對象的invoke方法裏,判斷真實View是否已經不存在了,如果真實View已經onDestory掉了,那就不做處理,如果真實View是存在的,那麼就通過method的invoke方法,將真實View和方法參數傳遞進去,從而達到調用真實View方法的目的(在invoke裏將方法的調用偷偷的替換到真實View方法的調用上)。

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