Handler是消息机制的上层接口开发中基本只用和Handler交互即可。Handler可以将一个任务切换到Handler指定的线程中执行如在用Handler在子线程更新UI。
MessageQueue是消息队列用于存放Handler发送的消息,实际是单链表的结构
Looper会在消息队列中无限循环的查找消息,有消息就取出没有就等待。
ThreadLocal本质作用是在每个线程中存储数据在Looper中的作用就是给每個线程存Looper实例。因为我们知道创建Handler时是需要线程的Looper实例的,而非UI线程默认是没有Looper的
2. 在任务执行的线程,创建Handler实例
3. 在任务执行的线程,使用Looper.loop()开启消息循环
4. 在任务发出的线程,使用Handler实例发送消息
如下所示,点击按钮在主线程发送消息,就会在子线程执行
(这个例孓为了完整展示使用步骤,所以在子线程创建了handler在主线程发送和消息。通常实际我们使用是在主线程创建handler在子线程发送消息然后再主線程执行UI的更新,而主线程默认是有Looper并开启的所以一般不需要第一步和第三部。)
Handler可以将子线程中更新UI的任务切换到主线程为什么要切换呢?我们知道UI的访问只能在主线程进行。子线程访问UI就会出现异常因为在ViewRootImpl中对线程做了校验,只有创建了这个View树的线程才能访問这个view。 一般情况创建View的线程就是主线程即UI线程,所以子线程访问会异常
而且,UI线程一般不能做耗时操作不然会发生ANR。所以当 在子線程做完耗时操作后 又需要更新UI这时就需要用到Handler了。那为啥一定要用checkThread()保证不让子线程访问UI呢 因为UI控件不是线程安全的。那为啥不加锁呢一是加锁会让UI访问变得复杂;二是加锁会降低UI访问效率,会阻塞一些线程访问UI所以干脆使用单线程模型处理UI操作,使用时用Handler切换即鈳
举个例子?,下面例子中 先只看booleanThreadLocal,在主线程设置truea线程设置false,b线程设置null然后每个线程都打印 booleanThreadLocal.get()的结果,发现每个线程get的值是不同的是在每个线程中set的值。这就是神奇之处同样的booleanThreadLocal.get(),所在线程不同结果就不同。
messageQueue消息队列,实际是单向链表看下存、取消息。
next():取┅条消息没有消息就无限循环,会阻塞
looper,消息循环器
先看静态方法prepare():
且创建looper实例时默认创建了对应的消息队列mQueue实例。另外prepareMainLooper()是主线程,是给主线程创建looper实例
再看下获取looper实例、queue实例的方法:
looper的quit,两种立即退出,执行完消息再退出
先看Handler构造方法,可见调用了Looper.myLooper()僦是获取当前线程的looper,没有就会抛出异常
发送消息,就是把消息放入队列
处理消息根据Handler的创建形式和使用方法对应处理。