asp做的手机网站,个人网站后台管理,重庆南岸区网站建设,网络规划与设计的目的案例4——异步任务内存泄漏
异步任务#xff0c;代指起子线程异步完成一些数据操作、网络接口请求等#xff0c;通常会使用以下API#xff1a;
Runnbale#xff0c;Thread,线程池RxJavaHandlerThread
而这些异步任务很有可能操作内存泄漏#xff0c;下面我们以Rxjava为…案例4——异步任务内存泄漏
异步任务代指起子线程异步完成一些数据操作、网络接口请求等通常会使用以下API
RunnbaleThread,线程池RxJavaHandlerThread
而这些异步任务很有可能操作内存泄漏下面我们以Rxjava为例演示此问题线程、线程池的问题也类似就不再一一演示了。 大多数项目的网络基础库传入Rxjava的是匿名Observer任务过多时未执行的任务的Observer会持有当前页面的引用造成内存泄漏接下来我们将演示这个场景
先提出几个问题
rxjava就会存在内存泄漏吗subscribe传入的匿名内部类Consumer实例不会造成内存泄漏吗异步任务返回时Activity已经处于onDestroyed状态Observer持有Activity引用Activity内存还能被回收吗
我们来验证一下rxjava的泄漏场景 假设我们在Activity#onResume方法里写了异步任务任务结束后设置view的属性在任务结束之前我们会调用Activity#finsh操作退出当前页面如下坨屎页面在12秒后实际已经处于onDestroyed状态了 为了演示问题我将延时时间增大写成12秒模拟异步任务返回的情况 Observable.timer(12000, TimeUnit.MILLISECONDS).subscribeOn(AndroidSchedulers.mainThread()).subscribe(new ConsumerLong() {Overridepublic void accept(Long aLong) throws Exception {dataBinding.layoutWelcome.setVisibility(View.GONE);...其他view 的引用}});测试步骤为
进入Activity立刻退出Activity一段时间之后观察Activity的内存是否被回收
我们得到一份hprof文件来分析下 老规矩先看下Instance-Details-Instance区域Activity的生命周期onDestroyed的值是否为true按步骤点击一看确实为true证明Activity已经离开窗口了处于销毁的生命周期中我们期望的时候垃圾回收器可以回收Activity占据的内存但事实上我们在Hprof文件看到了表明Activity占据的内存未回收。
紧着着我们面临下一个问题如何找到导致Activity内存泄漏的原因呢谁引用了Activity
点击Instance-Details-References区域我们可以很快得到答案按步骤点击Jump to Source 果然立刻跳转到内存泄漏所在的代码块终于我们通过分析hprof文件找到了问题所在: 那么如何解决此问题呢
rxjava提供了CompositeDisposable解决此类泄漏问题做法如下
创建实例对象 /*** 管理rxjava的任务及时释放不执行emitter#onNext*/public CompositeDisposable compositeDisposable new CompositeDisposable();用compositeDisposable实例去控制任务的生命周期 compositeDisposable.add(Observable.timer(12000, TimeUnit.MILLISECONDS).subscribeOn(AndroidSchedulers.mainThread()).subscribe(new ConsumerLong() {Overridepublic void accept(Long aLong) throws Exception {dataBinding.layoutWelcome.setVisibility(View.GONE);processIntent(getIntent());}}));页面生命周期onDestroyed期间清空任务 Overrideprotected void onDestroy() {super.onDestroy();compositeDisposable.clear();}总结
优化后的效果 优化后可看到Depth为空GC root 为空表明没有其他实例引用Activity了当垃圾回收器扫描到此实例该实例内存会被回收。 还记得开头的问题吗
rxjava就会存在内存泄漏吗答会存在consumer作为Activity的内部类持有当前Activity的引用任务未结束Activity已销毁就会出现内存泄漏subscribe传入的匿名内部类Consumer实例不会造成内存泄漏吗答只要是匿名内部类就很有可能内存泄漏上例子已经证明会产生内存问题。异步任务返回时Activity已经处于onDestroyed状态Observer持有Activity引用Activity内存还能被回收吗答无法被回收