概述
handler作为android消息处理的重要机制,全面回顾下其涉及的知识点。
关键类
整个消息处理机制中涉及到的主要类有:
Message : 负责消息封装
MessageQueue : 负责将消息封装为消息队列
Looper : 负责从消息队列中获取消息并分发
Handler : 负责消息发送及处理
Message
看看代码中的类注释:
定义包含描述和任意数据对象的消息,发送到Handler。 该对象包含两个额外的int字段和一个额外的对象字段,允许您在很多情形下不用分配新的对象。
虽然Message的构造函数是公共的,但最好的方法是是调用Message.obtain()或其Handler.obtainMessage()方法,从缓存池中获取一个Message对象。
讲的还是比较清楚,Mesasge的职责就是包装数据,缓存和生成Message。
那么来看看Message对象中的关键字段和方法:
public final class Message implements Parcelable {
//在handler处理消息时,用于区分消息内容
public int what;
//可携带int参数
public int arg1;
//可携带int参数
public int arg2;
//包装的消息对象
public Object obj;
//缓存池对象
private static Message sPool;
Message next;
private static int sPoolSize = 0;
//缓存池的大小
private static final int MAX_POOL_SIZE = 50;
//从全局的缓存池中获取一个新的Mesasge实例,避免分配新的对象
public static Message obtain() {
synchronized (sPoolSync) {
if (sPool != null) {
Message m = sPool;
sPool = m.next;
m.next = null;
m.flags = 0; // clear in-use flag
sPoolSize--;
return m;
}
}
return new Message();
}
//Message本身携带了target对象,也就是目标handler
//因此消息可以通过target进行发送
public void sendToTarget() {
target.sendMessage(this);
}
//message对象的回收缓存
void recycleUnchecked() {
// Mark the message as in use while it remains in the recycled object pool.
// Clear out all other details.
flags = FLAG_IN_USE;
what = 0;
arg1 = 0;
arg2 = 0;
obj = null;
replyTo = null;
sendingUid = -1;
when = 0;
target = null;
callback = null;
data = null;
synchronized (sPoolSync) {
if (sPoolSize < MAX_POOL_SIZE) {
next = sPool;
sPool = this;
sPoolSize++;
}
}
}
}
sPool是一个链表结构,在obtain()方法中,sPool为空的话将直接返回一个新的Message对象,如果不为空,那么就取当前对象返回,注意该方法使用synchronized进行代码块同步。
Message当中还存在其他的一些方法,基本都是用来辅助Message的构建和缓存的,这里不在列出了。
MessageQueue
看看代码中的类注释:
低级别类,包含要由Looper调度的消息列表。 消息不会直接添加到MessageQueue, 而是通过与Looper相关联的Handler对象。
您可以使用Looper.myQueue()检索当前线程的MessageQueue 。
由Looper类来进行调度,Message是由Handler对象处理才能放入MessageQueue中。
其中关键的字段和方法:
public final class MessageQueue {
Message mMessages;
//将Mesage入队
boolean enqueueMessage(Message msg, long when) {
//...省略代码
Message p = mMessages;
//...省略代码
if (p == null || when == 0 || when < p.when) {
//mMessages是空的,或者如果新msg的执行时间为0,或者小于当前mMessages的时间
//那么msg会成为链表的新头部
msg.next = p;
mMessages = msg;
needWake = mBlocked;
} else {
Message prev;
for (;;) {
prev = p;
p = p.next;
//一直找到队尾或者执行时间小于找到的message的时间
if (p == null || when < p.when) {
break;
}
if (needWake && p.isAsynchronous()) {
needWake = false;
}
}
//然后把新的msg插入进去
msg.next = p; // invariant: p == prev.next
prev.next = msg;
//...省略代码
}
}
//获取Message
Message next() {
//...省略代码
Message prevMsg = null;
Message msg = mMessages;
//...省略代码
for (;;) {
if (prevMsg != null) {
prevMsg.next = msg.next;
} else {
mMessages = msg.next;
}
msg.next = null;
if (DEBUG) Log.v(TAG, "Returning message: " + msg);
msg.markInUse();
return msg;
}
}
总的来说Looper负责消息的入队和出队,主要根据Message的执行时间来确定Message在链表中的位置,时间越小,在队列的中的位置就越靠前,被Handler执行的就越早。
Looper
类注释:
用于为线程运行消息循环的类。 默认情况下线程 没有与之关联的消息循环; 调用prepare方法来创建一个Looper对象来运行循环的线程中,然后调用loop方法让它处理消息,直到循环停止。
大多数与消息循环的交互都会通过Handler对象。
意思就是我们可以通过Looper.prepare()方法来获取一个当前线程的Looper对象。
其中关键的字段和方法:
public final class Looper {
//当前线程的ThreadLocal,保存了Looper对象
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
//application 的主Looper对象,负责整个App的消息处理
private static Looper sMainLooper; // guarded by Looper.class
//消息队列
final MessageQueue mQueue;
//准备Looper对象
public static void prepare() {
prepare(true);
}
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
//使用ThreadLocal来给当前线程设置一个Looper对象
sThreadLocal.set(new Looper(quitAllowed));
}
//Application 的主Looper对象,在ActivityThread这个类中调用该方法来生成Looper
public static void prepareMainLooper() {
prepare(false);
synchronized (Looper.class) {
if (sMainLooper != null) {
throw new IllegalStateException("The main Looper has already been prepared.");
}
sMainLooper = myLooper();
}
}
}
//获取Application的主Looper对象
public static Looper getMainLooper() {
synchronized (Looper.class) {
return sMainLooper;
}
}
//获取当前线程的Looper对象
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
//获取当前线程的MessageQueue对象
public static @NonNull MessageQueue myQueue() {
return myLooper().mQueue;
}
//从MessageQueue 中取出Message进行分发处理
public static void loop() {
final Looper me = myLooper();
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
final MessageQueue queue = me.mQueue;
//...省略代码
for (;;) {
//获取Message
Message msg = queue.next(); // might block
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
//...省略代码
try {
//使用Message包含的Handler对象进行消息的处理
msg.target.dispatchMessage(msg);
end = (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis();
} finally {
}
//...省略代码
//回收message
msg.recycleUnchecked();
}
}
从上面可以看出Looper对象的主要责任一个是生成整个Applicaion的主Looper对象,运行在UI线程,这一步是在ActivityThread的main()方法中调用的,如果是在子线程的话也可以生成不同的Looper对象,这样各个线程有属于自己的Looper对象,消息的处理互相不受影响。
另外就是从MessageQueue中取出Message发送到对应的Handler对象进行处理。
对于ThreadLocal类的一些分析:Android ThreadLocal及InheritableThreadLocal分析。
Handler
Handler中的关键注释:
Handler有两个主要用途:(1)安排消息和 runnables将在未来某个点执行; (2)在与您自己不同的线程上执行执行消息入队;
其中关键的字段和方法:
public class Handler {
//通常我们调用该方法来发送消息
public final boolean sendMessage(Message msg)
{
return sendMessageDelayed(msg, 0);
}
//该方法可以设置消息执行的延迟时间
public final boolean sendMessageDelayed(Message msg, long delayMillis)
{
if (delayMillis < 0) {
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
//该方法可以设置消息在指定的时间点运行
public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
MessageQueue queue = mQueue;
if (queue == null) {
RuntimeException e = new RuntimeException(
this + " sendMessageAtTime() called with no mQueue");
Log.w("Looper", e.getMessage(), e);
return false;
}
return enqueueMessage(queue, msg, uptimeMillis);
}
//最终消息进入MessageQueue的队列
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
//这里就将handler的引用传递个message对象了
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
//可以进行Runnable任务
public final boolean post(Runnable r)
{
return sendMessageDelayed(getPostMessage(r), 0);
}
//将Runnable任务封装成Message
private static Message getPostMessage(Runnable r) {
Message m = Message.obtain();
m.callback = r;
return m;
}
//处理消息,注意msg.callback和mCallback 的特殊情况,尤其是传入了
//mCallback 的情况下将不会走handleMessage()方法
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
//子类必须实现该方法来处理消息
public void handleMessage(Message msg) { }
}
总结
消息处理的整个执行流程:
Handler.sendMesasge();
Handler.sendMessageDelayed();
Handler.sendMessageAtTime();
Handler.enqueueMessage(),至此消息入队了;
Looper.loop()从MessageQueue中取出消息,分发给目标Handler;
Handler.handleMessage()
当然中间的一些特殊流程及处理要注意。