本篇文章是在已经会使用Handler并对handler有一定了解的情况下,对Handler的原理做探讨。
1. UI线程的Looper
UI线程的Looper的创建是在ActivityThread中创建的;
ActivityThread它管理应用进程的主线程的执行(相当于普通Java程序的main入口函数),并根据AMS的要求(通过IApplicationThread接口,AMS为Client、ActivityThread.ApplicationThread为Server)负责调度和执行activities、broadcasts和其它操作。
main函数源码:
在main函数里为UI线程创建了Looper,并启动Looper.loop()中的for循环来处理接收到的Message。
来看看Looper的源码;
在Looper中首先创建一个ThreadLocal常量,ThreadLocal在上篇博客中已有介绍;他就好比是一个小区管理员,Thread的实例(new Thread)就是这个小区的各个住户,每户住户房间的设备就是Looper(new Looper)实例;住户可以创建设备,也可以不创建,但每户只能有一套设备(即一个Thread 实例只能绑定一个Looper);小区管理员(ThreadLocal)记录每户住户(Thread实例)的信息,并为其分配钥匙;每个住户只要一把钥匙,只能开对应的房间门并使用该房间的设备。
Looper实例创建的主要过程
线程每次创建Looper实例之前,都会让小区管理员(ThreadLocal)检查一下该住户(线程实例)是否有设备(Looper实例),如果有就抛出异常,没有就创建,并由小区管理员(ThreadLocal)管理两者之间的关系,以保证每个住户(线程实例)最多只能有一套设备(Looper实例),且每套设备(Looper实例)只能属于一个住户(线程实例)。
MessageQueue创建比较简单,与Looper一同创建;Looper与MessageQueue一一对应;MessageQueue主要是用来存储管理Message。
以上就是UI线程的Looper和MessageQueue的创建过程。
2. 普通线程的Looper
普通线程的Looper创建过程和UI线程的创建过程相似,区别主要有三点:
1.UI线程的Looper是由系统创建的,在ActivityThread中创建。
2.普通线程的Looper是手动创建的,调用 Looper.prepare()和 Looper.loop();方法为此线程创建Looper。
3.UI线程的Looper不可以退出,普通线程的Looper可以退出。
3. Handler与Looper、MessageQueue的关系
先来看看Handler的创建:
myLooper()源码
由上图源码不难分析出,只要在同一线程中创建的Handler实例,其对应的Looper实例和MessageQueue都是一样的。
通过以上分析可以总结出Handler与Looper、MessageQueue、Thread有如下关系:
1.Looper 与 MessageQueue一一对应(即一对一关系)
2.Handler与Looper是多对一关系。
3.Thread与Looper也是一一对应关系(Thread最多只能有一个Looper)。
4. 消息的发送、存储、处理
Handler发送消息的方法有很多种,但最终调用的方法都是调用的都是sendMessageAtTime方法。
/**
* Enqueue a message into the message queue after all pending messages
* before the absolute time (in milliseconds) <var>uptimeMillis</var>.
* <b>The time-base is {@link android.os.SystemClock#uptimeMillis}.</b>
* Time spent in deep sleep will add an additional delay to execution.
* You will receive it in {@link #handleMessage}, in the thread attached
* to this handler.
*
* @param uptimeMillis The absolute time at which the message should be
* delivered, using the
* {@link android.os.SystemClock#uptimeMillis} time-base.
*
* @return Returns true if the message was successfully placed in to the
* message queue. Returns false on failure, usually because the
* looper processing the message queue is exiting. Note that a
* result of true does not mean the message will be processed -- if
* the looper is quit before the delivery time of the message
* occurs then the message will be dropped.
*/
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);
}
把Message加入到MessageQueue容器;
这里如果Handler发送了message就会被存储到对应的MessageQueue中。
再来看看Message的处理:
Message的处理是在Looper.loop()方法,重要的地方尽量做了注释:
/**
* Run the message queue in this thread. Be sure to call
* {@link #quit()} to end the loop.
*/
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;
// Make sure the identity of this thread is that of the local process,
// and keep track of what that identity token actually is.
Binder.clearCallingIdentity();
final long ident = Binder.clearCallingIdentity();
for (;;) {//for循环,始终遍历MessageQueue,如果有message就处理
Message msg = queue.next(); // might block
if (msg == null) {
return;
}
Printer logging = me.mLogging;
if (logging != null) {
logging.println(">>>>> Dispatching to " + msg.target + " " +
msg.callback + ": " + msg.what);
}
msg.target.dispatchMessage(msg);//重点:在保存message时就为此message绑定了Handler,
// 此时调用该Handler的dispatchMessage方法来处理消息
if (logging != null) {
logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
}
final long newIdent = Binder.clearCallingIdentity();
if (ident != newIdent) {
Log.wtf(TAG, "Thread identity changed from 0x"
+ Long.toHexString(ident) + " to 0x"
+ Long.toHexString(newIdent) + " while dispatching to "
+ msg.target.getClass().getName() + " "
+ msg.callback + " what=" + msg.what);
}
msg.recycleUnchecked();//msg处理完后就会被回收
}
}
Looper.loop()用一个死循环来遍历对应线程的MessageQueue,有Message就分发给与之绑定的Handler(调用Handler的dispatchMessage方法)处理。message绑定handler是在Handler发送消息时。
Handler的dispatchMessage处理消息的过程:
/**
* Handle system messages here.
*/
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);//处理post出来的Message。
} else {//处理send出来的Message
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {//如果实现Callback的handleMessage方法且返回为true则不再调用Handler的handleMessage方法
return;
}
}
handleMessage(msg);//如果没有实现Callback,或者实现Callback的handleMessage方法,但返回为false都会调用Handler的handleMessage方法
}
}
消息的发送、接收、处理大致如此。
总结:Handler、Looper、MessageQueue可以看成是一个生产者与消费者模式;Handler充当生成者,MessageQueue是一个容器,Looper是消费者;Handler最主要的作用就是 线程间通信
关于Handler的使用,以后再做介绍或参见其他博客。
以上仅为个人见解,如有指导意见请留言;也可加qq:1148392049