Handler内存泄漏
- 关于Handler内存泄漏及解决办法:
-
原因:
- handler会持有activity的匿名引用 (因为内部类的原因,具体参考内部类实现),当activity要被回收时,因为handler在做耗时操作而没有被释放,从而内存泄漏
- 实例化Handler对象后,它就会主动与主线程的Looper的消息队列关联起来,所有发送到消息队列的Message都会拥有一个对Handler的引用,所以才由Looper处理消息时的回调
Handler.handlerMessage(Message)
来处理消息
-
public class SampleActivity extends Activity { private Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { //... } } } 复制代码
-
解决办法:
-
将Handler设置为静态内部类(具体参考静态内部类和内部类区别),并使使Handler持有对Activity的弱引用
public class SampleActivity extends Activity { ....... private static class MyHandler extends Handler { private final WeakReference<SampleActivity> mActivity; public MyHandler(SampleActivity activity) { myActivity = new WeakReference<SampleActivity>(activity); } @Override public void handleMessage(Message msg) { SampleActivity activity = mActivity.get(); if (activity != null) { ... } } } } 复制代码
-
在activity生命周期
onDestroy()
中调用Handler.removeCallback()
方法// 清空消息队列,移除对外部类的引用 @Override protected void onDestroy() { super.onDestroy(); mHandler.removeCallbacksAndMessages(null); } //Handler源码中removeCallbacksAndMessages()注释含义 /** * Remove any pending posts of callbacks and sent messages whose * <var>obj</var> is <var>token</var>. If <var>token</var> is null, * all callbacks and messages will be removed. */ public final void removeCallbacksAndMessages(Object token) { mQueue.removeCallbacksAndMessages(this, token); } 复制代码
复制代码
-
-
内部类实现
- 内部类和静态内部类以及匿名内部类的应用
-
内部类的优势:
-
内部类方法可以访问盖内定义所在作用域的数据,包括私有数据
-
内部类可以对同一个包中其他类隐藏
-
想定义一个回调函数而且不像编写大量代码时,使用匿名内部类比较简洁
-
-
原理:
-
内部类的对象总有一个隐式引用,它指向了创建它的外部类对象
-
编译器修改了所有内部类的构造器,添加了一个外围类的引用参数:
public class Outer { ... class Inner { ... //Outer为外部类,Inner为内部类 Outer out; public Inner(Outer outer) { out = outer; } } } 复制代码
-
-
静态内部类: 使用内部类只是为了把一个类隐藏在另一个类的内部,并不需要内部类引用外围类的对象。 因此可以将内部类声明为static,以便取消产生的引用
-