動態(tài)代理模式-Android項目采用Mvp模式開發(fā)的一些問題

概述

現(xiàn)在有許多安卓app采用mvp模式進行開發(fā).
mvp是什么?
m層指的是數(shù)據(jù)層, 對數(shù)據(jù)進行各種處理.
v層一般是指activity或fragment, 它只關注ui界面.
p層及presenter, 它像一個主持人一樣, 作為中間人調用m層與v層, 將它們隔離開來, 從而達到解耦目的.

問題一

然而我們在用mvp模式開發(fā)的時候, 會遇到這樣一些問題:
一般來講, Activity會持有Presenter的引用, Presenter也會持有Activity的引用, 這就導致了一個問題, 當Activity退出銷毀后, 由于 P層仍持有Activity的引用, 導致Activity無法釋放, 最終會引起內存泄漏! 怎么辦呢? 網(wǎng)上也有許多解決方法, 把這個Activity用弱引用包裹一下 :

public abstract class BasePresenter<V extends IView> {
    /**弱引用, 防止內存泄漏*/
    private WeakReference<V> weakReference;

    /**
     * 關聯(lián)V層和P層
     */
    public void attatchView(V v) {
        weakReference = new WeakReference<>(v);
    }

    /**
     * @return P層和V層是否關聯(lián).
     */
    public boolean isViewAttached() {
        return weakReference != null && weakReference.get() != null;
    }

    /**
     * 斷開V層和P層
     * 在Acitivity的onDestory()中調用
     */
    public void detachView() {
        if (isViewAttached()) {
            weakReference.clear();
            weakReference = null;
        }
    }
    ...
}

問題二

當P層的邏輯處理完后, 我們就要調用V層來處理UI了, 怎么拿到V層的引用呢? 很簡單, 定義一個方法:

    public V getView() {
        return isViewAttached() ? weakReference.get() : null;
    }

但是這個方法有個很讓人不安的返回值, 它有可能返回null. 試想一下, 用戶打開了一個頁面(Activity), 這個頁面的P層去網(wǎng)絡請求, 也許網(wǎng)絡比較卡, 用戶沒等結果返回, 就退出了該頁面.此時網(wǎng)絡請求仍在繼續(xù).直到好不容易有結果返回的時候, P層調用getView()方法去更新ui, activity弱引用已經釋放掉了, getView()就會返回null, 就會發(fā)生喜聞樂見的空指針異常!
怎么辦? 辦法也很簡單, 在getView()方法調用的時候, 加一層判斷:

if(isViewAttached()){
    getView().xxxx
}

但作為一個偷懶的程序員, 我還是覺得這樣判斷太麻煩了, 有沒有一個自動幫我對getView()返回值判空的方法呢? 最好在BasePresenter類中都處理好了, 調用起來沒有后顧之憂就爽多了.
答案當然是有! 可以采用動態(tài)代理模式, 在attatchView()的時候, 生成Activity的代理類, 在每個Activity方法被調用之前判空下 Activity, 如果Activity存在, 就讓這個代理類執(zhí)行更新ui的方法, 如果被銷毀了, 就啥都不做. 廢話不多說, show code:

public abstract class BasePresenter<V extends IView> {

    /**弱引用, 防止內存泄漏*/
    private WeakReference<V> weakReference;
    private V mProxyView;

    /**
     * 關聯(lián)V層和P層
     */
    public void attatchView(V v) {
        weakReference = new WeakReference<>(v);
        MvpViewHandler viewHandler = new MvpViewHandler(weakReference.get());
        mProxyView = (V) Proxy.newProxyInstance(v.getClass().getClassLoader(), v.getClass().getInterfaces(), viewHandler);
    }

    /**
     * @return P層和V層是否關聯(lián).
     */
    public boolean isViewAttached() {
        return weakReference != null && weakReference.get() != null;
    }

    /**
     * 斷開V層和P層
     */
    public void detachView() {
        if (isViewAttached()) {
            weakReference.clear();
            weakReference = null;
        }
    }

    public V getView() {
        return mProxyView;
    }

    private class MvpViewHandler implements InvocationHandler {
        private IView mvpView;

        MvpViewHandler(IView mvpView) {
            this.mvpView = mvpView;
        }

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            //如果V層沒被銷毀, 執(zhí)行V層的方法.
            if (isViewAttached()) {
                return method.invoke(mvpView, args);
            }
            //P層不需要關注V層的返回值
            return null;
        }
    }

}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末糠雨,一起剝皮案震驚了整個濱河市洼怔,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌淳玩,老刑警劉巖厌蔽,帶你破解...
    沈念sama閱讀 217,734評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件畦贸,死亡現(xiàn)場離奇詭異愈污,居然都是意外死亡,警方通過查閱死者的電腦和手機涨缚,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,931評論 3 394
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來策治,“玉大人脓魏,你說我怎么就攤上這事⊥ū梗” “怎么了茂翔?”我有些...
    開封第一講書人閱讀 164,133評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長履腋。 經常有香客問我珊燎,道長,這世上最難降的妖魔是什么遵湖? 我笑而不...
    開封第一講書人閱讀 58,532評論 1 293
  • 正文 為了忘掉前任悔政,我火速辦了婚禮,結果婚禮上延旧,老公的妹妹穿的比我還像新娘谋国。我一直安慰自己,他們只是感情好迁沫,可當我...
    茶點故事閱讀 67,585評論 6 392
  • 文/花漫 我一把揭開白布芦瘾。 她就那樣靜靜地躺著,像睡著了一般集畅。 火紅的嫁衣襯著肌膚如雪近弟。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,462評論 1 302
  • 那天挺智,我揣著相機與錄音祷愉,去河邊找鬼。 笑死赦颇,一個胖子當著我的面吹牛谣辞,可吹牛的內容都是我干的。 我是一名探鬼主播沐扳,決...
    沈念sama閱讀 40,262評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼泥从,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了沪摄?” 一聲冷哼從身側響起躯嫉,我...
    開封第一講書人閱讀 39,153評論 0 276
  • 序言:老撾萬榮一對情侶失蹤纱烘,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后祈餐,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體擂啥,經...
    沈念sama閱讀 45,587評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,792評論 3 336
  • 正文 我和宋清朗相戀三年帆阳,在試婚紗的時候發(fā)現(xiàn)自己被綠了哺壶。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,919評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡蜒谤,死狀恐怖山宾,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情鳍徽,我是刑警寧澤资锰,帶...
    沈念sama閱讀 35,635評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站阶祭,受9級特大地震影響绷杜,放射性物質發(fā)生泄漏。R本人自食惡果不足惜濒募,卻給世界環(huán)境...
    茶點故事閱讀 41,237評論 3 329
  • 文/蒙蒙 一鞭盟、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧瑰剃,春花似錦懊缺、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,855評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至舀凛,卻和暖如春俊扳,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背猛遍。 一陣腳步聲響...
    開封第一講書人閱讀 32,983評論 1 269
  • 我被黑心中介騙來泰國打工馋记, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人懊烤。 一個月前我還...
    沈念sama閱讀 48,048評論 3 370
  • 正文 我出身青樓梯醒,卻偏偏與公主長得像,于是被迫代替她去往敵國和親腌紧。 傳聞我的和親對象是個殘疾皇子茸习,可洞房花燭夜當晚...
    茶點故事閱讀 44,864評論 2 354

推薦閱讀更多精彩內容