Android Handler和内部类的正确用法

引言

在Android中如果错误的使用Handler也会引起内存泄漏的。所以在我们实际开发中还是需要多多注意,并尽量去避免它。

原例

Android代码中涉及线程通信的地方,我们基本都会选择使用Handler。比如:

public class HandlerActivity extends Activity{
	//可能引起内存泄漏的方法
	private final Handler mHandler = new Handler(){
		@Override
		public void handlerMessage(Message msg){
		//...
		}
	}
}

如果使用Android Lint分析这段代码的话,会发现提示:

This Handler class should be static or leaks might occur.

 这就是在提醒开发者,这里的写法有可能会引起内存泄漏,需要开发者去处理。那为什么会可能产生内存泄漏呢?这个要从Handler的机制来说,我们都知道Handler是和Looper以及MessageQueue一起使用的。在Android中一个应用启动后,系统会默认创建一个为主线程服务的Looper对象,该对象用于处理主线程的所有Message对象,它的生命周期贯穿于整个应用的生命周期。在主线程中使用的Handler都会默认绑定到这个Looper对象。在主线程中创建Handler对象时,它会立即关联主线程Looper对象的MessageQueue,这时发送到MessageQueue中的Message对象都会持有这个Handler对象的引用,这样在Looper处理消息时才能回调到Handler的handleMessage方法。因此如果Message还没有被处理完成,那么Handler也就不会被垃圾回收。
 在上段代码中,我们将Handler的实例声明为了HandlerActivity的内部类。而在Java中非静态内部匿名类会持有外部类的一个隐式的引用,这样就又能能会导致外部类无法被垃圾回收。因此,最终由于MessageQueue中的Message对象还没有处理完成,就会持有Handler对象的引用,而非静态的Handler对象会持有外部类HandlerActivity的引用,这个Activity无法被垃圾回收,从而导致了内存泄漏。
比如下面这种写法:

public class HandlerActivity extends Activity{
	//可能引起内存泄漏的方法
	private final Handler mHandler = new Handler(){
		@Override
		public void handlerMessage(Message msg){
		//...
		}
	}
	@Override
	protected void onCreate(Bundle savedInstanceState){
		super.onCreate(savedInstanceState);

		//延迟5分钟发送消息
		mHandler.postDelayed(new Runnable(){
			@Override
			public void run(){
				...
			}
		},1000*60*5)
	}
}

由于消息要延后5分钟发送,因此,当用户进入这个Activity并在5分钟内退出后,在消息发送并处理完成之前,这个Activity是不会被系统回收的。
那么要怎么解决呢?有两个方案:

  • 在子线程中使用Handler,这时需要开发者自己创建一个Looper对象,这个Looper对象的生命周期同一般的Java对象,因此这种用法没有问题。
  • 将Handler声明为静态的内部类,前面说过,静态内部类不会持有外部类的引用,因此,也不会引起内存泄漏。

正确用法

所以,下面我们看下经典的用法:

public class HandlerActivity extends Activity{
	//声明一个静态的Handler内部类,并持有外部类的弱引用
	private static class InnerHandler extends Handler{
		private final WeakReference<HandlerActivity> mActivity;
		public InnerHandler(HandlerActivity activity){
			mActivity = new WeakReference<HandlerActivity>(activity);
		}
		@Override
		public void handleMessage(Message msg){
			HandlerActivity activity = mActivity.get();
			if(activity != null){
			//...
			}
		}
	}
	private final InnerHandler mHandler = new InnerHandler(this);
	//静态的匿名内部类不会持有外部类的引用
	private static final Runnable sRunnable = new Runnable(){
		@Override
		public void run(){
			//...
		}
	}
	@Override
	protected void onCreate(Bundle savedInstanceState){
		super.onCreate(savedInstanceState);
		//延迟5分钟发送消息
		mHandler.postDelayed(sRunnable,1000*60*5);
	}
}
    原文作者:Yang_Farley
    原文地址: https://blog.csdn.net/farley119/article/details/82872602
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞