MVP内存泄漏全解(笔记)
Posted 巨头之路
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MVP内存泄漏全解(笔记)相关的知识,希望对你有一定的参考价值。
前言
基于MVP 模式的理解进行内存泄漏的测试
1.对MvpSample2工程的测试(测试记录)
-
第一次: 清理弱引用和解除rx的订阅,rx里面没开线程跑,虽然栈中存在presenter$tologin$1,但是引用为0.,所以内存不泄漏
-
第二次:清理弱引用和解除rx的订阅,rx里面开了新的线程跑,presenter对象被线程所持有,activity引用不存在,presenter的内存泄漏了
-
第三次:清理弱引用和解除rx的订阅,rx里面上游开了循环(在上游的线程跑),虽然内存中存在presenter$tologin$1,内存不泄漏,跟第一次一样
-
第四次:没有清理弱引用和解除rx的订阅,rx里面没开线程跑,虽然内存中存在presenter$tologin$1,但是引用为0.,所以内存不泄漏
-
第五次:没有清理弱引用和解除rx的订阅,rx里面上游开了循环(在上游的线程跑),presenter的引用被rx上游线程持有,释放不了,内存泄漏了,而View已经不存在内存,是因为View在P层中加了弱引用
-
第六次:V在P层中是强引用持有,没有解除rx的订阅,rx里面上游开了循环(在上游的线程跑), presenter和View都回收不了,因为线程持有P的引用,还在运行中
-
第七次:V在P层中是强引用持有,解除rx的订阅,rx里面上游开了循环(在上游的线程跑), 虽然内存中存在presenter$tologin$1,但是引用为0.,所以内存不泄漏
2.截图说明
-
截图1 :从GC Roots节点到该对象(LoginPresenter)的最短引用路径, 排除弱引用/软引用
-
截图2 : 从截图1过渡到截图2,可以看到LoginPresenter是被线程持有引用
-
截图3 : 从profiler可以看到LoginPresenter是被线程持有引用
-
截图4 : 从profiler可以看到LoginModel是被LoginPresenter持有引用,LoginPresenter是被线程持有引用
-
截图5 : objects是存在实例的个数,Shallow Heap浅堆是Java对象占用的内存,Retained Heap深堆是java对象及对象引用的类占用的内存、jvm gc回收时释放的内存
-
截图6:V被P强引用持有引用,P被运行的任务(可能内部类)持有引用,导致V层和P层都内存泄漏
3.总结:
-
p层的耗时任务在页面销毁时是否执行很关键:假设当页面销毁时,presenter层内的任务执行完,由于presenter没有再被内部类等持有引用,所以presenter是会被回收的,那view层也不被presenter持有引用,所以即使没在View销毁时清空软引用和置View为null,View同样会被销毁,不存在内存泄漏问题
-
V层是否被presenter弱引用持有决定V层是否会内存泄漏:假设当页面销毁时,presenter层内的任务在执行, 由于V是被presenter弱引用持有,所以V是会被GC回收的,而Presenter由于任务还在执行,所以回收不了
-
页面销毁时结束耗时任务可解决presenter和View的内存泄漏, 假设当页面销毁时,即使presenter对View是强引用持有,只要此时任务执行完或者解绑Rx的订阅,presenter和View都是可以被回收的,所以不存在内存泄漏
-
Rx上游创建异步耗时线程跑,即使取消订阅,还是会内存泄漏,可能Rx不知道开了一个子线程在跑,而子线程持有presenter的引用
-
线程的调度放心交给Rx来处理:Rx上游创建异步耗时线程跑,即使取消订阅,还是会内存泄漏,可能Rx不知道开了一个子线程在跑,而子线程持有presenter的引用 (这里参考链接 在Rx的上游执行异步耗时任务的测试)
-
所以发生泄漏主要在: presenter的引用被rx开辟的线程所持有(或者Model的引用被持有), 从而导致V的引用被持有
-
线程运行中,而View界面已经关闭,由于presenter不能被回收(被内部类持有引用),所以导致presenter内存泄漏
-
而如果View是被Presenter强引用持有的话,那View也不能被回收
-
而如果View是被presenter弱引用持有的话,那么View是可以被GC回收的
-
-
View的界面销毁, 此时线程运行结束或解除rx的订阅,由于presenter已不再被持有引用,故可GC回收, 而不管View是被Presenter强引用还是弱引用,View都会被GC回收
-
-
MVP的内存泄漏可以通过解除Rx的订阅(RxLifecycle2框架或AutoDispose框架)来解决,前提是耗时任务都在Rx里去操作, 使得Model、View、Presenter不被持有引用,从而可回收
4.参考
使用AndroidStudio提供的Android Profiler工具和mat进行内存泄漏析
以上是关于MVP内存泄漏全解(笔记)的主要内容,如果未能解决你的问题,请参考以下文章