1.Handler
是用来将任务切换到Handler
所在的线程的,并不只是更新UI
,只是常被用来更新UI
。Android UI
线程是不安全的,如果多个线程更新UI
可能造成不可预料的后果,所以Android
规定不能在非UI
线程中更新UI
,在进行UI
操作的时候ViewRootImpl
会去检查当前线程是否是UI
线程,不是就抛异常,故此我们常用Handler
来切换线程。
2.MessageQueue
内部存储结构其实是单链表,负责存储消息。
3.Looper
会无限循环地去查找MessageQueue
是否有新消息,有就处理,否则就阻塞等待。Handler
创建时会采用当前的Looper
来构建消息循环,如果没有Looper
就抛异常,所以Handler
创建之前先初始化Looper
(调用Looper.prepare()
方法)或在有Looper
的线程中创建。UI
线程之所以不用初始化Looper
,是因为在Activity
初始化的时候就新建了一个Looper
,属于后者。
4.ThreadLocal
可以在不同线程中互不干扰地存储并提取数据,也就是说,相当于每个线程都分配了一个本地的数据块用来存放或提取本线程的数据。在Handler
中主要用来在线程中存取Looper
。
5.Handler
处理消息原理:
(1)Looper.prepare()
初始化Looper
,这里初始化内部的MessageQueue
,并把当前线程对象存起来;
(2)创建Handler
,这里获取当前线程的Looper
对象,并获取Looper
的MessageQueue
,获取不到Looper
就抛异常;
(3)Looper.loop()
开启无限循环,在循环里面会去调用MessageQueue
的next
方法获取消息对象,只要消息对象不为空就分发出去(调用Looper
的quit
方法会改变MessageQueue
的mQuitting
标志,next
方法会返回null),否则跳出循环,next
里面也是个无限循环,查询消息队列里面是否有待处理的消息(每个Message
对象都有个时间标志,到点了就是可以处理),有就取出消息并移除这个消息,没有就阻塞等待;
(4)Handler
调用post
(最终都调用send
方法)或send
方法发送消息,最后都是调用sendMessageAtTime
方法,方法里面调用(5);
(5)MessageQueue
调用enqueueMessage
方法将消息放入消息队列,这里是按照消息的时间顺序插入的,最新的在最前面;
(6)在(3)中的循环中Looper
检查到有新消息(最新的消息),调用Handler
的dispatchMessage
方法,进一步调用Runnable
或Handler
的handMessage
方法;。
(7)Looper
是运行在Handler
创建的线程中,因此Looper
在处理过程中就将线程切换到Handler
所在线程了。
网友评论