Android开发——Handler引起的内存泄露
2015-08-30 11:05
561 查看
在Android异步消息处理中,
但当我们这么写时,编译器会给出警告提示:Handler类应该是静态的,可能发生内存泄漏。
这里Handler是一个匿名内部类的实例,其持有外面的Activity的引用,所以当Handler伴随一个耗时后台线程时就会出现Activity无法回收,进而内存泄露。
因为静态的内部类不会持有外部类的引用,所以不会导致外部类实例的内存泄露。由于Handler不再持有外部类对象的引用了,导致程序不允许你在Handler中操作Activity中的对象。所以如果要在静态内部类中调用外部的Activity时,我们使用弱引用来处理(WeakReference)。
二:postDelayed(new Runnable(),10000)情况
在handler的post方法中我们加入了一个匿名的runnable,同时我将其执行延迟了10秒。
被延迟的消息会在被处理之前一直存在于主线程消息队列中。同时new Runnable也是匿名内部类实现的,同样也会持有Activity的引用。
这时候我们还需要将Runnable设置为静态的成员属性。
同时onCreate()中mHandler.postDelayed(sRunnable, 10000);
另一个方法是使用Handler的removeCallbacksAndMessages ()方法,把消息对象从消息队列移除。
当参数为null的时候,可以清除掉所有跟次handler相关的Runnable和Message,我们在onDestroy中调用次方法清理掉所有Messages。
使用静态的内部类;
对所有handler/Runnable中的变量都用弱引用。
关于引用:
参考
http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2014/1123/2047.html
/article/1382695.html
Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { // } };
但当我们这么写时,编译器会给出警告提示:Handler类应该是静态的,可能发生内存泄漏。
原因:
在Java中,非静态的内部类和匿名内部类都会隐式地持有其外部类的引用。静态的内部类不会持有外部类的引用。这里Handler是一个匿名内部类的实例,其持有外面的Activity的引用,所以当Handler伴随一个耗时后台线程时就会出现Activity无法回收,进而内存泄露。
解决方法:
一:将Handler声明为静态内部类。因为静态的内部类不会持有外部类的引用,所以不会导致外部类实例的内存泄露。由于Handler不再持有外部类对象的引用了,导致程序不允许你在Handler中操作Activity中的对象。所以如果要在静态内部类中调用外部的Activity时,我们使用弱引用来处理(WeakReference)。
private static class MyHandler extends Handler { private final WeakReference<SampleActivity> mActivity; public MyHandler(SampleActivity activity) { mActivity = new WeakReference<SampleActivity>(activity); } @Override public void handleMessage(Message msg) { SampleActivity activity = mActivity.get(); if (activity != null) { // ... } } }
二:postDelayed(new Runnable(),10000)情况
mHandler.postDelayed(new Runnable() { @Override public void run() { // } }, 10000);
在handler的post方法中我们加入了一个匿名的runnable,同时我将其执行延迟了10秒。
被延迟的消息会在被处理之前一直存在于主线程消息队列中。同时new Runnable也是匿名内部类实现的,同样也会持有Activity的引用。
这时候我们还需要将Runnable设置为静态的成员属性。
private static final Runnable sRunnable = new Runnable() { @Override public void run() { /* ... */ } };
同时onCreate()中mHandler.postDelayed(sRunnable, 10000);
另一个方法是使用Handler的removeCallbacksAndMessages ()方法,把消息对象从消息队列移除。
当参数为null的时候,可以清除掉所有跟次handler相关的Runnable和Message,我们在onDestroy中调用次方法清理掉所有Messages。
protected void onDestroy() { super.onDestroy(); mHandler.removeCallbacksAndMessages(null); };
总结:
当我们使用非静态内部类时,如果其实例的持有对象的生命周期大于其外部类对象,那么就有可能导致内存泄露。方案:使用静态的内部类;
对所有handler/Runnable中的变量都用弱引用。
关于引用:
• 强引用:如“Object obj = new Object()”,这类引用是Java程序中最普遍的。只要强引用还存在,垃圾收集器就永远不会回收掉被引用的对象。 • 软引用:它用来描述一些可能还有用,但并非必须的对象。在系统内存不够用时,这类引用关联的对象将被垃圾收集器回收。JDK1.2之后提供了SoftReference类来实现软引用。 • 弱引用:它也是用来描述非需对象的,但它的强度比软引用更弱些,被弱引用关联的对象只能生存岛下一次垃圾收集发生之前。当垃圾收集器工作时,无论当前内存是否足够,都会回收掉只被弱引用关联的对象。在JDK1.2之后,提供了WeakReference类来实现弱引用。 • 虚引用:最弱的一种引用关系,完全不会对其生存时间构成影响,也无法通过虚引用来取得一个对象实例。为一个对象设置虚引用关联的唯一目的是希望能在这个对象被收集器回收时收到一个系统通知。JDK1.2之后提供了PhantomReference类来实现虚引用。
参考
http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2014/1123/2047.html
/article/1382695.html
相关文章推荐
- Android5.1中调试PreferenceActivity的时候,back键无效的问题处理
- android studio 真机运行中文乱码
- Android XML属性介绍
- 为了学习android,开始写博客了
- Android(java)学习笔记202:Handler消息机制的原理和实现
- Android基础知识巩固:关于PendingIntent和广播
- android 应用自动更新
- Android中Unable to execute dex: Multiple dex files define Lcom/viewpagerindicator/CirclePageIndicat
- Android 开发 AutoCompleteTextView结合自定义的适配器,查询数据库
- Android 技巧
- 导入导出Android手机文件
- 学习笔记——Android创建应用程序和活动
- android自定义时间选择器
- Android资源管理框架(Asset Manager)简要介绍和学习计划
- Android中TimePickerDialog的使用
- 从零开始学Android之监听器实现监听动作的三种方式(匿名内部类,独立类,接口方式)
- android studio中配置opencv问题
- android 状态栏沉浸
- 获取资源ID失败--android使用友盟第三方登陆错误解决
- Android之——自定义下拉菜单的实现