概述
Android的消息机制是由Handler+MessageQueue+Looper三个成为整体共同协作的工作过程。其中Handler可将一个任务切换到指定的线程中去。
在日常开发中,我们都知道系统规定我们必须在主线程(UI线程)中去操作UI控件,同时不建议我们在主线程中执行耗时的操作。
为什么不能在子线程中更新UI呢?因为UI控件是不安全的,但是如果用锁的机制又会影响访问的效率和逻辑变得复杂。ViewRootImpl对UI操作做了验证,验证的方法是checkThread来完成的。
消息的发送:
- Handler调用send方法发送消息
- send方法会调用MessageQueue的enqueueMessage方法将消息放入消息队列中去
Looper发现有新的消息时,到最后会调用Runable或者Handler的handlerMessage方法
其中Looper是运行在创建Handler所在的进程中ThreadLocal的工作原理
ThreadLocal:是一个线程内部的数据储存类,他可以把数据储存到指定的线程中去,然后
在指定的线程才能获取保存在该线程中的数据,其他线程访问不到这些数据。
在Looper、ActivityThread的、AMS都用到了ThreadLocal。
ThreadLocal用法:它可以指定要操作的类型,在不同线程中设置不同的值。
set方法
1.获取当前线程
2.根据当前线程获取Values(内部类)对像
3.将ThreadLocal的值储存到table(Object[])数组中去
4.将ThreadLocal的引用储存在table[index]中
5.将ThreadLocal的value保存在table[index+1]中get方法
1.获取当前线程
2.根据当前线程获取指定的Values对象
3.找到ThreadLocal中引用对象在table中的位置,然后在下一个位置找到ThreadLocal的值
消息队列的工作原理
消息队列在Android中指的是MessageQueue:
- 插入消息
enqueueMessage方法:往消息队列中插入一条消息,其实它就是一个链表的插入操作 - 读取消息
next方法:从消息队列中取出一条消息并且从队列中移除该消息它会无限循环,如果消息队列没有消息,则它会阻塞在这里当有新的消息来时,它会返回这条消息并从链表中移除。
Looper的工作原理
Looper在Android的消息机制中扮演着消息循环的角色,不停地从MessageQueue中查看是否有新消息
在Looper在构造方法中它会创建一个MessageQueue,并将当前的线程保存起来
通过Looper.prepar()即可创建一个Looper,接着通过Looper.loop()来开启消息循环
Looper中的PrepareMainLooper方法,主要是给主线程使用的,它的本质也是prepare方法来实现的,
Looper还提供一个getMainLooper方法来获取主线程的Looper。
退出Looper:
- quite方法:直接退出Looper
quitSafely方法:设定一个退出标记,然后把消息队列中的消息处理完之后再安全退出
建议在不需要的时候终止Looper
loop方法:里面是一个死循环,唯一能够跳出来的条件是MessageQueue的next方法返回null。 当调用 Looper的quit方法时,MessageQueue的quit或者quitSafely方法来通知消息队列退出,当消息队列被标记为退出状态时,它的next方法会返回null。
在源码中:其中有msg.target,这是一个Handler,它调用dispatchMessage方法,即将消息交由这个方法处理。
Handler的工作原理
Handler发送消息:仅仅是向消息队列插入一条消息,MessageQueue的next方法将消息传给Looper,Looper将收到的消息进行处理,然后交由Handler(dispatchMessage方法)。
Handler处理消息的过程:
- 检查它的callback是否为空,不为空即通过handlerCallback方法来处理消息
- 检查mCallback是否为空,如果不为空即调用mCallback的handleMessage方法处理消息
- 调用Handler的handleMessage方法来处理消息
Handler的特殊构造方法:this(looper,null,false),这就说明了如果当前线程没有Looper的话,则会抛出异常
主线程的消息循环
Activity的主线程就是ActivityThread,入口为main方法
main方法里面通过Looper.preparMainLooper来创建主线程的Looper和MessageQueue,然后调用Looper.loop方法进行主线程的消息循环
ActivityThead.H是一个Handler,内部定义了一组消息类型,主要包含四大组件的启动和停止
ActivityThread通过ApplicationThread和AMS进行进程间的通信
AMS->回调ApplicationThread中的Binder方法->ApplicationThread向H发送消息->H将逻辑切换到ActivityThread中执行