杭州Android培训
达内杭州Android培训中心

13732203138

热门课程

Android Handler错误的使用

  • 时间:2018-03-27 17:47
  • 发布:杭州android中心
  • 来源:疑难解答

Handler,我们列举一个常用的源码例子:

public class TestActivity extends Activity {

private Handler mHandler = new Handler() {

@Override

public void handleMessage(Message msg) {

// ...

}

}

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

// 延时30秒发送消息

mHandler.postDelayed(new Runnable() {

@Override

public void run() { 

// ...

}

}, 30 * 1000);

}

}

经常需要在Activity中创建内部类,如上使用Handler这种场景还是很多的,但是如上程序可能导致严重的内存泄漏

内存泄露分析:

首先我们要明确如下几个基本概念:

1.内部类对象肯定持有外部类对象的引用

2.Android系统垃圾回收机制释放的是没有任何引用指向的对象内存 (这里我们不讨论具体垃圾回收机制原理,后续抽空整理详细解读)

如上创建了一个Handler的匿名内部类,内部类持有外部类Activity的引用。

我们还需要简单了解Handler,Message,Looper三者的关系,网上也有很多文章介绍,后面我也会用一篇文章来说明。

当一个Android应用程序第一次启动时,Android框架为应用程序的主线程创建一个Looper对象。

一个Looper实现了一个简单的消息队列MessageQueue,在一个循环中处理Message对象。

所有主要的应用程序框架事件(如活动生命周期方法调用,单击按钮,等等)都包含在Message对象,它被添加到Looper的消息队列然后一个个被处理。主线程的Looper在应用程序的整个生命周期中存在。

当一个Handle在主线程被实例化,它就被关联到Looper的消息队列,在Handler发送消息时候,会给Messgae的target赋值为handler自身的引用,然后加入MessageQueue中,也就是MessageQueue队列中有Handler的引用。

那么如果Activity退出,这时候MessageQueue中还有Message消息对象,那么也就是还有Handler对象引用,而Handler对象有持有外部类Activity的引用,那么根据垃圾回收机制,我们就知道这样会导致Activity对象不能释放,那么内存泄露就出现了。

解决Handler引起的内存泄露:

1. Handler的子类可以使用静态内部类。静态内部类不会隐式持有外部类的引用。所以不会导致它的Activity泄漏。

2. 如果你需要在Handle内部调用外部Activity的方法,那么让Handler持有一个Activity的弱引用(WeakReference)以便你不会意外导致context泄漏。

3. 为了解决我们实例化匿名Runnable类可能导致的内存泄漏,我们将用一个静态变量来引用他(因为匿名类的静态实例不会隐式持有他们外部类的引用)。

4. 在Activity onDestroy的时候,取消掉该Handler对象的Message和Runnable,避免有例子代码中延迟消息Message导致Handler对象无法释放

如下测试源码可以参考

public class TestActivity extends Activity {

/**

* 静态内部类的实例不会隐式持有外部类的引用

*/

private static Handler mHandler = new Handler() {

@Override

public void handleMessage(Message msg) {

// ...

}

}

/**

* 匿名类的静态实例不会隐式持有他们外部类的引用

*/

private static final Runnable sRunnable = new Runnable() {

@Override

public void run() {

// ...

}

};

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

// 延时30秒发送消息

mHandler.postDelayed(sRunnable, 30 * 1000);

}

/**

* 在Activity onDestroy实现中取消掉该Handler对象的所有Message和Runnable

*/

@Override

protected void onDestroy() {

mHandler.removeCallbacks(sRunnable);

}

}

上一篇:Android分享功能
下一篇:理解Android MD设计
选择城市和中心
贵州省

广西省

海南省