Android的消息机制分析
Android的消息机制分析实际上就是Handler的运行机制,主要包括Handler、MessageQueue和Looper。而在Looper工作原理中使用到了一个重要的类:ThreadLocal。为了更好的理解Looper的工作原理,我们先来了解一下ThreadLocal。
ThreadLocal
ThreadLocal是线程内部的数据存储类,通过它可以在指定线程中存储数据,而且只能在指定线程中获取到所存储的数据,在其他线程中无法获取到数据。在Android源码中,Looper、ActivityThread以及AMS都用到了ThreadLocal。就拿Hander来举例,Handler需要获取到当前线程的Looper, 很显然Looper的作用域就是当前线程,而且不同线程具有不同的Looper,这时候通过TheardLocal就可以在当前线程中存储Looper,而且还保证了在当前线程中的独享。
原理:在不同线程中访问同一个ThreadLooper的get方法,ThreadLooper内部会从各自线程中取出一个数组,然后再从数组中根据当前的ThreadLoal的索引去查找对应的value值。很显然,不同线程中的数组是不同的,这就是为什么通过ThreadLoal可以在不同线程中维护一套数据的副本并且彼此互不干扰。
MessageQueue
消息队列MessageQueue主要包含两个操作:插入enqueueMessage和读取next。
enqueueMessage的作用: 负责往消息队列中插入一条消息。
next的作用: 负责从消息推列中取出一条消息并将其移除。next 是一个无限循环的方法,如果消息推列中没有消息,那么next方法会一直阻塞。
Looper
在Android中,消息处理线程启动后会进入一个无限的循环体(Looper)之中,每循环一次,从其内部的消息队列中取出一个消息(先进先出),然后回调相应的消息处理函数,执行完成一个消息后则继续循环。若消息队列为空,线程则会阻塞等待。
Looper负责的就是创建一个MessageQueue,然后进入一个无限循环体不断从该MessageQueue中读取消息,而消息的创建者就是一个或多个Handler 。
首先Looper.prepare()
在本线程中保存一个Looper实例,然后该实例中保存一个MessageQueue对象;因为Looper.prepare()
在一个线程中只能调用一次,所以MessageQueue在一个线程中只会存在一个。
Looper.loop()
会让当前线程进入一个无限循环,会调用MessageQueue的next
方法来获取新消息,而next
是一个阻塞操作,当没有新消息时,这也导致了loop
方法也会阻塞。如果MessageQueue的next
方法返回了新消息,Looper会回调msg.target.dispatchMessage(msg)
方法,而Hander的dispatchMessage
方法是执行在创建Hander时所使用的Looper中,这样就成功的将代码逻辑切换到指定线程中执行。
Handler
Handler的构造方法,会首先得到当前线程中保存的Looper实例,进而与Looper实例中的MessageQueue想关联。
Handler的sendMessage方法,会给msg的target赋值为handler自身,然后加入MessageQueue中。Message的callback是一个Runnable对象,实际上就是Handler的post
方法所传递的Runnable参数。
在构造Handler实例时,我们会重写handleMessage
方法,也就是msg.target.dispatchMessage(msg)
最终调用的方法。
注意事项
注意:在实际开发过程中,handler引起的内存泄漏以及解决办法
原因:非静态内部类持有外部类的匿名引用,导致外部activity无法被释放
解决办法
1,handler内部持有外部activity的弱引用,
2,把handler改为静态内部类,
3,在ondestroy方法中调用mHandler.removeCallback()
参考自:http://blog.csdn.net/lmj623565791/article/details/38377229