Android的消息机制主要是指Handler的运行机制,而Handler的运行离不开MessageQueue和Looper的支撑。
其中MessageQueue称为消息队列,用作存储一组消息,并以队列的形式对外提供插入和删除工作
(具体实现:使用单链表的结构来存储消息列表)。
MessageQueue不能处理消息
;
Looper称为循环,会以无限循环方式去查找消息和处理消息。
如何获取当前线程的Looper(
创建Handler对象时需要当前线程Looper来构造消息系统循环
)?通过ThreadLocal可获取每个线程的Looper(ThreadLocal在不同的线程中互不干扰的存储和提供数据)。
一、Android的消息机制概述
1)Handler主要作用:
将一个任务切换到某个指定的线程中执行;
2)子线程不能访问UI原因:
A)子线程访问UI,会抛出异常;
原因是ViewRootImpl对UI操作左了验证和限制---->UI只能由Android主线程访问。
B)UI控件不是线程安全的;
不加锁原因:防止UI逻辑复杂以及UI访问效率低。
3)Handler的工作过程:A)当send方法调用时,会调用MessageQueue的enqueueMessage方法将消息放入消息队列中;B)然后
Looper发现有新的消息就会处理这个消息
,最终消息中的Runnable或者handleMessage方法被调用。
注意:处理消息是在创建Handler所在线程中。
二、ThreadLocal的工作原理
ThreadLocal是一个线程内部的数据存储类,
通过它可以在指定的线程中存储数据,数据存储后,
只有在指定线程中可以获取到存储数据
,对于其他线程是无法获取的。eg:
在主线程设置mBooleanThreadLocal为true;在子线程1设置其为false;在子线程2不设置,然后通过
同一个mBooleanThreadLocal的get方法
获取值,
然而3个线程中mBooleanThreadLocal的值不一样。
原因:不同线程访问同一个ThreadLocal的get方法,
ThreadLocal内部会从各自线程的中取出一个数组
(每个线程内数组不同)
,然后再从数组中根据当前ThreadLocal的索引去查找对应的value值。
2.1 ThreadLocal的set方法
1)首先先通过values方法获取当前线程的TheadLocal数据;如何获取?在Thread类的内部有一成员专门
用于存储线程的ThreadLocal数据
:ThreadLocal.Values
localValues;
2)在localValues内部有一数组:Object[] tables,ThreadLocal的值就是存放在tables数组中。也即通过
localValues的put方法将value值存储到数组中:
2.2 ThreadLocal的get方法
1)第一步,同样是取出当前线程的localValues对象;如果对象为null,直接返回初始值;
2)如果对象不为null,从localValues对象中取出table数组,并从数组中获取value。
总结:
从上面set和get源代码可以看出,它们的操作对象都是当前线程的localValues对象的table数组,导致在不同线程中访问同一个ThreadLocal对象的set和get方法,它们对ThreadLocal所做的读/写操作仅限于各自线程的内部。
三、消息队列的工作原理
Android中消息队列是指MessageQueue。MessageQueue主要包含两个操作:插入和读取。
1)插入:
由enqueueMessage方法完成;
往消息队列中插入一条消息;单链表的插入
2)读取:
由next方法完成;
从消息队列中取出一条消息并将其从消息队列中删除。如果消息队列中没有消息,next方法会阻塞,当新消息到来时,next方法会返回这条消息并将其从单链表中删除。
四、Looper的工作原理
不停从MessageQueue中查看是否有新的信息,如果有新的信息就会立刻处理
,否则就一直阻塞。
4.1 Looper的构造函数
1)创建一个MessageQueue消息队列;
2)将当前线程对象保存下来;
4.2 为线程创建Looper对象
1)通过Looper.prepare()即可为当前线程创建一个Looper对象;
2)通过Looper.loop()来开启消息循环;
3)getMainLooper()方法可以在任何地方获取到主线程的Looper。
五、Handler的工作原理
Handler的工作主要包含:
消息的发送和接收过程
。1)消息的发送是通过post方法以及
send一系列方法完成的。
5.1 消息的发送
源代码如下:
1)
Handler发送消息的过程
:
向消息队列中插入一条消息,MessageQueue的next方法就会返回消息给Looper;
2)
Looper收到消息就开始处理
,最终
消息由Looper交给Handler处理
,也即
Handler的dispatchMessage方法被调用。
5.2 消息的处理
1)首先,
检查Message的callback是否为null,不为null就通过handleCallback来处理消息
;Message的Callback是一个Runnable对象(post方法所传递的Runnable参数)
2)其次
,检查mCallback是否为null,不为null就调用mCallback的handleMessage方法来处理消息。
其中
Callback是个接口
,其接口方法需要在子类实现。
3)最后,
调用Handler的handleMessage方法来处理消息
。其流程如下:
5.3 Handler的构造函数
1)通过特定的Looper来构造Handler:
2)通过默认构造方法: