Handler.Callback()避免内存泄漏

 

Android进阶_Handler和Handler.Callback和Message

标签: Handler.CallbackHandlerMessageandroid
  2052人阅读  评论(0)  收藏  举报
  分类:

最近得病了,看到代码黄色警报不是很爽。虽然不影响运行,但是看着代码不干净不利索。


Handler,线程通信,用的比较多吧,今天写代码一如往常的:

[java]  view plain  copy
 print ?
  1. private Handler smsHandler = new Handler(){  
  2.     public void handleMessage(Message msg) {  
  3.           
  4.     };  
  5. };  
感觉没什么错误,怎么出黄色警报了。

This Handler class should be static or leaks might occur 

大体意思是说 Handler应该是静态的,否则会造成内存溢出。

然后将Handler用static修饰,ok,警报消失。


但是遇到问题了:不设置成静态会造成内存溢出?要毁三观?然后就开始寻求网络资源的帮助

http://www.cnblogs.com/jevan/p/3168828.html

在这里找到了答案,MessageQueue中的消息队列会一直持有对handler的引用,而作为内部类的handler会一直持有外部类的引用,就会导致外部类不能被GC回收。当我们发延时很长的msg时就容易出现泄漏。所以此处应该设置为static,然后Handler就会跟随类而不是跟随类的对象加载,也就不再持有外部类的对象引用。

单单这个问题可以直接看上面这篇文章。


通过搜索还找到了另一个解决黄色警报的解决方案:在新建Handler对象的时候传入一个Handler.Callback对象。

[java]  view plain  copy
 print ?
  1. private Handler mHandler = new Handler(new Handler.Callback() {  
  2.   
  3.     @Override  
  4.     public boolean handleMessage(Message msg) {  
  5.         return false;  
  6.     }  
  7. });  
以前还没注意过这个参数呢,这个方法,返回值都是干啥的?

然后去看了一下这一块的源码:

[java]  view plain  copy
 print ?
  1. /** 
  2.  * Callback interface you can use when instantiating a Handler to avoid 
  3.  * having to implement your own subclass of Handler. 
  4.  * 
  5.  * @param msg A {@link android.os.Message Message} object 
  6.  * @return True if no further handling is desired 
  7.  */  
  8. public interface Callback {<span style="white-space:pre"> </span>// callback接口  
  9.     public boolean handleMessage(Message msg);  
  10. }  
  11.   
  12. /** 
  13.  * Subclasses must implement this to receive messages. 
  14.  */  
  15. public void handleMessage(Message msg) {  
  16. }  
  17.   
  18. /** 
  19.  * Handle system messages here. 
  20.  */  
  21. public void dispatchMessage(Message msg) {  
  22.     if (msg.callback != null) { // callback是msg中的一个字段,是一个Runnable对象,当通过handler.post方法发送一个runnable的时候就会被封装到这个msg中  
  23.         handleCallback(msg); // 此方法是Handler中的一个静态方法,方法体:message.callback.run();只有这一句,可以看出是直接调用的run()方法,没有新建线程,否则也不符合这里线程通信了对吧。  
  24.     } else {  
  25.         if (mCallback != null) { // mCallback就是上面接口的对象  
  26.             if (mCallback.handleMessage(msg)) { // 如果返回true直接return结束方法,不再调用handler中的<span style="font-family: Arial, Helvetica, sans-serif;">handleMessage方法。</span>  
  27.                 return;  
  28.             }  
  29.         }  
  30.         handleMessage(msg);// handler中的消息处理方法  
  31.     }  
  32. }  

Looper从MQ中拿到一个msg就会调用handler中的dispatchMessage方法,然后有此方法进行分发处理。想到触摸时间分发了木有?

最后记录一下Message对象的获取,原来一直使用Message.obtain方法来获取,今天无意间发现了handler.obtainMessage方法也可以获取。

通过源码发现,其实handler.obtainMessage最终也是调用了Message中的一系列obtain方法。

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值