错误示例:延时post runnable,匿名的runnable隐式持有activity的引用,造成内存泄漏。
解决方案:
A、在activity的onDestroy方法中调用handler的removeCallbacksAndMessages方法,移除所有的回调和消息,使得runnable在activity回收时处于可回收状态,避免内存泄漏;
B、利用static内部类和弱应用WeakReference来避免内存泄漏;
错误示例:内部类AsyncTask持有外部activity的引用,当内部类的生命周期超出activity时(如横竖屏切换)导致内存泄漏;
解决方案:此类内部类必须为静态内部类,且在该静态内部类中持有外部类的弱应用,以此来防止内存泄漏。
thread要在合适的时机进行quit或者close
错误示例:
解决方案:
在onDestroy中添加如下代码
Utility.getInstance().setListener(null);
防止外部后台进程持有listener,listener隐式持有activity造成泄漏
四、基线中的进行网络请求大部分使用匿名内部callback类,匿名callback隐式持有外部activity的引用,也可能造成内存泄漏错误示例:
解决方案:
避免内部匿名类,用静态内部类替换,并持有activity的弱引用更新相关UI,若不是执行UI相关,则直接处理逻辑即可。
错误实例:
此种写法,后期未做任何处理,可能导致内存泄漏。
在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设置退出逻辑条件。