Handler 引起的内存泄漏
关联文章:
Android OOM 分析
Android 基于Handler 剖析消息机制
Android 中Handler详解
Android HandlerThread详解
Handler发送的消息通过obtain获取
前言:
对于Handler 在android 系统引起的内存泄漏,网上已经有了很多优秀的博文,我这边也是参考了它们并结合自己的经验进行总结,希望利己利人。
举例说明:
在java中非静态内部类和匿名内部类都会隐式持有当前类的外部引用,由于Handler是非静态内部类所以其持有当前Activity的隐式引用,如果Handler没有被释放,其所持有的外部引用也就是Activity也不可能被释放,当一个对象一句不需要再使用了,本来该被回收时,而有另外一个正在使用的对象持有它的引用从而导致它不能被回收,这导致本该被回收的对象不能被回收而停留在堆内存中,这就产生了内存泄漏,并最终造成了OOM。
来看下例子:
public class MainActivity extends Activity {private int[] array = new int[1024 * 1024];private Handler mHandler = new Handler() {@Overridepublic void handleMessage(Message msg) {super.handleMessage(msg);}};/** Called when the activity is first created. */@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);mHandler.postDelayed(new Runnable() {@Overridepublic void run() {//}}, 1000 * 60 * 5);}
}
代码中:
- 申请一个大概4M 的数组空间
- Handler 会延迟5分钟post
问题验证:
经过几次back 退出应用之后,来看下内存情况:
这个时候即使是一直GC,也无法回收mem,再来一次操作后:
再次多出4M左右的空间,GC还是无法回收
解决办法:
解决这个问题思路就是使用静态内部类并继承Handler时(或者也可以单独存放成一个类文件)。因为静态的内部类不会持有外部类的引用,所以不会导致外部类实例的内存泄露。当你需要在静态内部类中调用外部的Activity时,我们可以使用弱引用来处理。另外关于同样也需要将Runnable设置为静态的成员属性。修改后不会导致内存泄露的代码如下:
public class MainActivity extends Activity {private int[] array = new int[1024 * 1024];/** Called when the activity is first created. */@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);actionTo();}private static class MyHandler extends Handler {private final WeakReference mActivity;public MyHandler(Activity activity) {mActivity = new WeakReference(activity);}@Overridepublic void handleMessage(Message msg) {super.handleMessage(msg);}}private static final Runnable mRunnable = new Runnable() {@Overridepublic void run() {//}};private void actionTo() {MyHandler mHandler = new MyHandler(this);mHandler.postDelayed(mRunnable, 1000 * 60 * 5);}
}
其他更多关于泄漏的case 可以看下 Android OOM 分析
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
