内部类与内存泄漏(Handler,Runnable)

利用多线程+Handler来完成UI的交互是常见的操作,而匿名Runnable对象的使用也是在多线程使用时常用的,那么使用时会在什么情况下导致内存泄漏的发生呢?


  1. 首先看以下的代码:

<span style="white-space:pre">	</span>public class MainActivity extends Activity {
	
		@Override
		protected void onCreate(Bundle savedInstanceState) {
			super.onCreate(savedInstanceState);
			setContentView(R.layout.activity_main);
			
			mLeakHandler.postDelayed(new Runnable() {
				
				@Override
				public void run() {
					// TODO Auto-generated method stub
					
				}
			}, 60*60*1000);
		}
	
		private final Handler mLeakHandler = new Handler() {
	
			@Override
			public void handleMessage(Message msg) {
				// TODO Auto-generated method stub
				super.handleMessage(msg);
			}
			
		};
		

}


 

 

  1. Android lint工具中会有以下的警告信息:

ThisHandler class should be static or leaks might occur

  1. 内存泄漏如何会发生呢?首先看以下的知识:
    1. android应用第一次启动时,framework会在主线中创建一个Looper对象(Looper对象实现了一个简单的消息队列,生命周期跟应用相同,其管理的消息包括Activity lifecycle方法的调用,Button点击事件,当然也包括我们主动调用的,handler.sendMessage
    2. Handler对象在主线程实例化以后,其就会与Looper消息队列关联到一起,队列上的Message对象持有Handler引用,使得Looper处理某个消息时,会调用Hander#handlerMessage方法。
    3. java中,非静态内部类和匿名内部类持有隐式的外部类引用,而静态内部类没有隐式引用。
    4. Activity finish之后,延迟处理消息在主线程消息队列中保持1个小时,知道消息最终处理,消息中有Handler引用,而Handler有外部类MainActivity引用,这样ActivityContext就不能被回收,匿名Runnable对象同理
  1. 如何修改原来的程序?

只需要将Handler类和Runnable改为静态内部类。

如何调用外部类的方法?

可以通过内部静态类持有外部类的弱引用来实现;

  1. 具体修改代码如下:

<pre name="code" class="java">	protected void onCreate(Bundle savedInstanceState) {
			super.onCreate(savedInstanceState);
			setContentView(R.layout.activity_main);
			
			mHandler.postDelayed(mRunnable, 60*60*1000);
		}
	
		
		private static class MyHandler extends Handler {
			private final WeakReference<MainActivity> mActivity;
			
			public MyHandler(MainActivity activity) {
				mActivity = new WeakReference<MainActivity>(activity);
			}
			
			@Override
			public void handleMessage(Message msg) {
				// TODO Auto-generated method stub
				super.handleMessage(msg);
			}
			
		}
	
		private final MyHandler mHandler = new MyHandler(this);
		private static Runnable mRunnable = new Runnable() {
			
			@Override
			public void run() {
				// TODO Auto-generated method stub
				
			}

};


 

 

  1. 其他:
    1. PendingIntentsend方法,如果某个类调用PendingIntent.send(),并且传入非静态内部类Handler类,也会导致内存泄漏;
    2. 如果想要重用,可以创建一个通用类:

		public abstract class WeakReferenceHandler<T> extends Handler {
			private WeakReference<T> mReference;
			
			public WeakReferenceHandler(T reference) {
				mReference = new WeakReference<T>(reference);	
			}
		
			@Override
			public void handleMessage(Message msg) {
				// TODO Auto-generated method stub
				super.handleMessage(msg);
				if(mReference.get() == null)
					return ;
				handleMessage(mReference.get(), msg);
			}
			
			protected abstract void handleMessage(T reference, Message msg);
			
		}
		
		private final MyHandler2 mHandler2 = new MyHandler2(this);
			
			private static class MyHandler2 extends WeakReferenceHandler<MainActivity> {
		
				public MyHandler2(MainActivity reference) {
					super(reference);
					// TODO Auto-generated constructor stub
				}
		
				@Override
				protected void handleMessage(MainActivity reference, Message msg) {
					// TODO Auto-generated method stub
					
				}
				

}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值