Mvp 框架 中 v层与p层之间如何防止内存泄漏?(面试题)

1、内存泄漏原因


内存泄漏就是当 GC 来回收时,然而这些对象没有得到释放,或者被其它的给引用了,这种情况下 GC 是不会自动回收的,而这块内存就会被一直占用着,得不到释放,这就是内存泄漏的基本概念。然而,程序这样的情况越来越多时,程序就会出现卡顿、奔溃、报异常的现象,当这些对象占用的内存达到一定的临界值时,机器中没有多余可用的内存,这时你再去申请内存空间,就会发生 OOM (内存溢出)。所以说,内存泄漏是一种安全隐患,它直接影响的是程序的性能。要想在这方面做的好,这需要一个深入的研究。

1、Mvp项目中

BaseMVP 其实也是会造成内存泄漏的一大安全隐患,它的内存泄漏是来自于 View 层与 Presenter 层之间的强引用关系。我们在 Presenter 层直接绑定了 View 才可以拿到 View 层的引用,它们之间是强引用的关系,如果不进行解绑的话,那就会造成内存泄漏的情况发生。为什么不解绑就会内存泄漏呢?我们来看看代码:

(不是最终版代码)
public abstract class BasePresenter<V extends IBaseView> implements IBasePresenter {
    protected V mView;
 
    @SuppressWarnings("unchecked")
    @Override
    public void attech(IBaseView view) {
        mView = (V) view;
    }
 
    @Override
    public void detech() {
//        mView = null;
    }
}

这里,我们不解绑 View,也就是 mView = null 注释掉,意味着 Presenter 层还持有 View 的引用,当 Activity 被关闭时,Activity 相当于 View 层,由于 Activity 还是被 Presenter 层引用了,当 GC 来了,它一看 Activity 被引用了,所以就不会去回收它。当你再次打开 Activity 又关闭时,Activity 又申请了一段新的内存空间,GC 又没去回收它,久而久之,势必会内存溢出。
而这里置空了就不会造成内存泄漏,因为此时的 View,也就是 Activity 的引用被释放了,如果再也没有其他类引用到 Activity 对象的时候,当 GC 来时,发现 Activity 是可以回收的,就把它回收掉了,这段内存空间就释放了。
说了这么多,其实就是为了介绍我们自己写的 BaseMVP 存在的内存泄漏问题,这里的代码还是基于上一篇 MVP v2 版本进行修改,因为 V 与 P 之间是强引用,
所以我们就改为弱引用用的方式,避免内存泄漏导致的 OOM 情况发生。

(此为kotin代码)
open class BasePresenter<V: IBaseView>:
    IPresenter<V> {

    protected var mView:V? = null
    private var weakReference:WeakReference<V>? = null
    protected var compositeDisposable:CompositeDisposable? = null

    override fun attachView(view: V) {
        weakReference = WeakReference(view)
        mView = weakReference!!.get()
    }

    protected fun addSubscribe(disposable:Disposable){
        if(compositeDisposable == null) compositeDisposable = CompositeDisposable()
        compositeDisposable!!.add(disposable)
    }

    protected fun unSubscribe(){
        if(compositeDisposable != null){
            compositeDisposable!!.clear()
        }
    }

    override fun detachView() {
        this.mView = null
    }
}

使用弱引用的方式让 P 层持有 V 层的引用,并且提供了 get() 方法给 P 层调用,父类 View 变量进行私有化,防止子类对其进行更改造成的其他错误。我们的 MainPresenter 获取 Activity 的引用就可以使用 get() 方法获得。弱引用在内存降到不足的情况下,GC 就会进行优先回收释放那些以弱引用方式引用的对象,一定程度上去避免内存溢出(OOM)。

动态代理

每次都要让 View 做空判断,很烦?

为什么要用动态代理呢?我们看上面的 get()代码,没次都需要判断 null 类型,是不是非常麻烦,又因为这里的 View 类型是一个接口(V extends IBaseView)泛型接口,所以这就好办了,动态代理完全就可以做到统一的空类型判断。
使用动态代理之后,我们在 Presenter 的实现类中就不需要做 View 层的空类型判断了,这样既节省了代码,虽然没有多少代码,但是写起来还是很烦的,又让我们的代码变得更加优雅。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,165评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,720评论 1 298
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,849评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,245评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,596评论 3 288
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,747评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,977评论 2 315
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,708评论 0 204
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,448评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,657评论 2 249
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,141评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,493评论 3 258
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,153评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,108评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,890评论 0 198
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,799评论 2 277
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,685评论 2 272

推荐阅读更多精彩内容

  • 1、Activity生命周期? onCreate() -> onStart() -> onResume() -> ...
    王培921223阅读 2,378评论 0 11
  • 所有知识点已整理成app app下载地址 J2EE 部分: 1.Switch能否用string做参数? 在 Jav...
    侯蛋蛋_阅读 2,358评论 1 4
  • 【Android 内存泄漏】 引用: ★★★ 【知识必备】内存泄漏全解析,从此拒绝ANR,让OOM远离你的身边,跟...
    Rtia阅读 743评论 0 2
  • 部署项目可以分为构建、发布两个步骤。构建过程打包源代码,生成最终运行的文件,发布过程使用打包后的文件更新线上程序。...
    wuww阅读 455评论 0 0
  • 文/执笔成书 新的一年已然开始了,又要开始一年的生活了,在这新的一年里,还有很多事要做。 第一,我得努力学习,并且...
    执笔成书阅读 123评论 0 2