Android
的消息机制主要是指Handler
的运行机制,Handler
并不是专门用于更新UI
的,只是大部分场景中被用作更新UI
Q:为什么不允许在在子线程访问UI
A:因为源码中限制了线程,他会检查当前线程是否主线程,不是就不给访问UI
。更重要的原因是控件并不是线程安全的,多线程操作会使他凉凉。设计者不把控件做成线程安全是因为加锁的话导致访问UI
变得复杂,以及效率低下。
void checkThread() {
if (mThread != Thread.currentThread()) {
throw new CalledFromWrongThreadException(
"Only the original thread that created a view hierarchy can touch its views.");
}
}
ThreadLocal
ThreadLocal
是JDK中的类,Thread类中有一个ThreadLocalMap
类变量,他初始为空值,负责记录该线程下的所有ThreadLocal
以及ThreadLocal
对应的值。ThreadLocal
其实是作为key从ThreadLocalMap
中存取对应的值,由于每个Thread
都有一个ThreadLoaclMap
,所以使用同一个ThreadLocal
在不同线程的Map中取得的值是不同的。
MessageQueue
消息队列,类似一个链表,从中取消息时,若里面没有消息,则阻塞
Looper
loop()
之后只有当消息列队取出空值时loop才会结束,而让MessageQueue.next()
返回空值的方式有两种,Looper.quit()
(直接中断),Looper.quitSafely()
(做标记,执行完当前任务再退出),Looper
与线程是一对一的关系, 当Looper
的loop()
方法调用后,当前线程的Looper
才具有了把Message
调度到当前线程执行的能力,也就是说,Handler
机制的线程调度能力其实来自于Looper
。
Handler
可以在任何线程中构造Handler
,但要是线程中没有Looper
的话就凉凉,无法构造,因为Handler
也存在一个消息队列,正是来自Looper
,没有Looper
,队列就为空;其次,一个没有了Looper
的Handler
什么也做不了,完全跨不了线程。Handler
不过就是用来告诉Looper
消息该怎么处理的东西而已,甚至于说我们可以连handler
的实例化派生类都不用写,直接使用Handler类本身,通过Handler.Callback
或者Message.Callback
来告诉Looper
该怎么处理消息