Handler和它的朋友们(流程、内存泄露相关)
流程:
1.Looper.prepare()
为当前线程set一个Looper(通过ThreadLocal.set方法)
新创建的Looper里面有一个MessageQueue的成员变量
2.Handler handler = new Handler();
handler得到一个当前线程的Looper对象(通过ThreadLocal.get方法),从而得到Looper的MessageQueue对象
Looper:
3.Looper.loop()
死循环将MessageQueue里面的Message对象交给handler处理
//因为这个方法里面有个死循环,Looper.loop()后面的代码不能被执行。
msg.target.dispatchMessage(msg); //此方法就是将message分配到Handler处理
4.handler.sendMessage
将这个Message进行入队操作(通过创建Handler时得到MessageQueue对象)
内存泄露
This Handler class should be static or leaks might occur问题
如果在一个Activity或者其他类中定义了一个Handler的非静态内部类,AndroidStudio会出现以下提示:
原因:
1.非静态的内部类持有其外部类的引用,所以这里的Handler内部类持有Activity的引用。
2.从上面第四步可以看出:handler.sendMessage方法会调用enqueueMessage,enqueueMessage方法会让发送的message对象持有当前的Handler的引用(看标注1)。
引用链如下图
3.如果Activity调用finish时,Handler的MessageQueue中还有未处理的Message,这个Message持有Handler的引用,Handler持有Activity的引用,这样会使得Activity不能被回收,而引起内存泄露,直到所有的MessageQueue中的Message处理完毕(Message的recycleUnchecked方法会使target置空(看标注2),Message不再持有Handler的引用)。
另外如果调用的是sendMessageDelayed,那么在delay到达前,message也会一直持有handler的引用,此时Activity调用finish,Activity也是不能被回收。
还有一种情况就是,耗时任务的线程(下载图片)持有handler的引用(sendMessage通知主线程进度),Activity调用finish时,耗时任务线程没执行完毕,Activity也不能被回收。
解决办法:
1.将Handler改为静态内部类,构造方法传进Activity,并定义为弱引用
2.在Activity onDestory方法调用
handler.removeCallbacksAndMessages(null);
但这种只能解决Message引用Handler,Handler引用Activity这种情况。
转载于:https://my.oschina.net/stphwn/blog/1813694