handler消息机制理解

253 阅读2分钟

handler负责消息的发送和处理,发送消息最终调用到handler.enquemessage(),然后调用到messagequeue.enquemessage(),方法,将消息发送到messagequeue维护的链表中,并将发送者handler赋给message.target。

message,表示消息,代表一个个事件,可以说message是事件的载体。在一个app中有大量的message对象被创建回收,因此在Message类中以单链表的数据结构封装了message全局池,通过Message.obtain()的方式获取,如果获取不到再新建一个message。调用recycle()回收不使用的Message对象。利于消息的复用,利于节约资源和内存。

messagequeue维护着一个消息队列,单链表数据结构,利于节约资源和内存,其元素物理存储内存不需要连续,依靠指针连接下一节点。

looper是消息驱动,会调用messagequeue.next()不断轮询messagequeue中的消息,如果有消息就取出删除并调用message.target.dispatchemessage(),回调message的处理结果,如果没有消息则阻塞在next()方法里。

消息机制实现线程间通讯,一个线程只能有一个looper,一个messagequeue,可以有多个handler。Loop.preparelooper(),创建一个looper对象,并在创建looper的同时创建一个messagequeue对象。

主线程在activitythread的main方法中已经创建了一个looper并调用了loop()开启了循环,所以主线程可以直接创建handler实例,发送处理handler消息而不报错。子线程如果要使用handler必须先调用prepare()创建looper并调用Loop()开启轮询。

handler引发内存泄露的理解:内存泄露本质上是长生命周期的对象引用了短生命周期的对象,导致短生命周期对象完成任务了还不能被垃圾回收机制回收。我们使用handler无论写成内部类还是匿名内部类都会持有外部类如activity的对象,message持有handler对象,messagequeue持有message对象,looper持有messagequeue,而looper是与线程绑定的。整个流程 activity—>handler—>message——>messagequeue—>looper—>当前线程;activity被当前线程持有,无法回收,引发内存泄漏。

解决内存泄漏:将handler定义成静态内部类,内部持有activity的弱引用,在activity.destroy()中调用handler.removecallbackandmessage(null)。