内存泄漏常见case总结

一、使用handler延时post匿名类造成的内存泄漏

错误示例:延时post runnable,匿名的runnable隐式持有activity的引用,造成内存泄漏。

 

解决方案

A、在activity的onDestroy方法中调用handler的removeCallbacksAndMessages方法,移除所有的回调和消息,使得runnable在activity回收时处于可回收状态,避免内存泄漏;

 

B、利用static内部类和弱应用WeakReference来避免内存泄漏;

 

二、用AsyncTask、Handler、Thread内部类时导致的内存泄漏,以AsyncTask为例

错误示例:内部类AsyncTask持有外部activity的引用,当内部类的生命周期超出activity时(如横竖屏切换)导致内存泄漏;

解决方案:此类内部类必须为静态内部类,且在该静态内部类中持有外部类的弱应用,以此来防止内存泄漏。

thread要在合适的时机进行quit或者close

三、匿名内部类Listener导致的内存泄漏

错误示例:

解决方案:

在onDestroy中添加如下代码

Utility.getInstance().setListener(null);

防止外部后台进程持有listener,listener隐式持有activity造成泄漏

四、基线中的进行网络请求大部分使用匿名内部callback类,匿名callback隐式持有外部activity的引用,也可能造成内存泄漏

错误示例

解决方案

避免内部匿名类,用静态内部类替换,并持有activity的弱引用更新相关UI,若不是执行UI相关,则直接处理逻辑即可。

 

五、基线使用JobManagerUtils执行后台任务时,post匿名runnable,需要及时cancel

错误实例:

此种写法,后期未做任何处理,可能导致内存泄漏。

在activity的onDestroy中,需要对还未来得及执行的任务进行cancel处理

解决方案:

1、如果是执行多个任务,如上,在post的时候,给我们的任务一个Tag,在onDestroy时,返回该tag下还未执行的任务,执行cancel操作。

2、如果是执行单个任务,可以记录此job,在合适的时机cancel此job(一般在onDestroy)

3、和之前分析的多个案例类似,将post的runnable以静态内部类的形式实现,不使用匿名内部类,这个解决方案就不再赘述。

总结解决方案及注意事项:

1、  类似handler、AsyncTask及Thread类等对象可能存在后台线程执行的类,避免在activity中使用其非静态内部类或匿名类,尽量使用静态内部类,

并引用activity的弱引用来获得外部类activity的引用,也不干扰外部activity的回收;

2、 在activity的onDestroy方法中,进行handler的remove, asyncTask的cancle等方法,及时终止移除不需要的后台线程的执行

3、 Java永远不会清理回收正在运行的threads。当Activity结束销毁时也不会帮我们把正在运行的thread也结束回收掉,Java threads会一直存在,

只有当线程运行完成或被杀死掉,线程才会被回收。所以一定要在合适的时机手动thread设置退出逻辑条件

Guess you like

Origin blog.csdn.net/cpcpcp123/article/details/121654703