一个流程总结,可参考源码理解
ThreadLocal有两个作用:1、作为线程内部的数据存储,它存储的是一个副本,所以各个线程是不一样的。2、复杂逻辑下的对象传递,比如监听器的传递,作为副本引用可以贯穿整个线程,而且不同线程又不一样,可以线程内部任何地方获取监听器。
首先明确的是handler、looper、messageQueue三者是被使用在线程中的,无论主线程还是子线程(都是线程)。
1、首先调用Looper.prepare()(主线程调用了Looper.prepareMainLooper())进行初始化,此时会new一个Looper实例并且会给sThreadLocal(**ThreadLocal是解决线程安全问题一个很好的思路,ThreadLocal类中有一个Map,用于存储每一个线程的变量副本,Map中元素的键为线程对象,而值对应线程的变量副本,由于Key值不可重复,每一个“线程对象”对应线程的“变量副本”,而到达了线程安全。
**)。并且prepare()智能调用一次,否则户出现异常。
2、在Looper的构造方法中创建了MessageQueue并保存Looper中,由于Looper.prepare()只会执行一次,所以MessageQueue实例也只有一个。
此时完成了Looper和MessageQueue的创建并完成了关联。
3、然后实例化Handler,在Handler的构造方法中通过Looper.myLooper()获取了Looper对象(实际上调用了sThreadLocal.get()),进而也就获取到了MessageQueue实例。
此时完成了Handler、Looper、MessageQueue三者的关联。
4、然后执行Looper.loop()方法。进行死循环、阻塞方式执行MessageQueue中的Message。
5、MessageQueue中的Message来源于Handler,Handler.sendMessage()最终执行Handler的enqueueMessage(),从而将要执行的Message加入MessageQueue中(Handler构造函数中获取。)然后Looper.loop()中执行Message并调用msg.target.dispatchMessage(msg)(msg.target在enqueueMessage()中赋值为Handler实例本身)。dispatchMessage()方法又执行了handleMessage()。从而完成了整个流程。
乱弹
利用这种异步消息处理机制不仅可以完成UI更新。还可以完成多线程间的通信等。
网友评论