1. 介绍
上一节完成了对Message类的分析,在Handler消息模型中,Message类是对消息的封装体,本节要介绍的是Looper类,该类的作用是循环询问MessageQueue是否还有要执行的消息,然后将获取到的消息分发出去。
2. 源码分析
首先看下Looper类几个重要的属性信息
private static final ThreadLocal sThreadLocal = new ThreadLocal();
final MessageQueue mQueue;
Thread mThread;
private static Looper mMainLooper = null;
其中sThreadLocal 代表当前线程的ThreadLocal,mQueue代表该Looper关联的MessageQueue(一个Looper仅有一个MessageQueue关联),mThread代表当前的线程,mMainLooper代表UI线程的Looper
其中Looper的文档介绍这样构建一个新的Handler消息处理模型。
class LooperThread extends Thread {
* public Handler mHandler;
*
* public void run() {
* Looper.prepare();
*
* mHandler = new Handler() {
* public void handleMessage(Message msg) {
* // process incoming messages here
* }
* };
*
* Looper.loop();
* }
* }
所以我们首先看下Looper.prepare()方法
public static final void prepare() {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper());
}
第2行:从ThreadLocal尝试取Looper对象,如果不为空,就会抛出运行时异常,因为一个线程直接对应一个Looper对象,也就是prepare方法也只能被调用一次。这里通过Looper空构造创建的对象
private Looper() {
mQueue = new MessageQueue();
mRun = true;
mThread = Thread.currentThread();
}
其中主线程的mainLooper是通过prepareMainLooper方法定义的,内部也是调用Looper.prepare()方法完成Looper初始化操作,另外给myLooper起名为mainLooper而已。
public static final void prepareMainLooper() {
prepare();
setMainLooper(myLooper());
if (Process.supportsProcesses()) {
myLooper().mQueue.mQuitAllowed = false;
}
}
这样对Looper类属性进行赋值
接下来看Looper.loop()方法的定义
public static final void loop() {
Looper me = myLooper();
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();
while (true) {
Message msg = queue.next(); // might block
//if (!me.mRun) {
// break;
//}
if (msg != null) {
if (msg.target == null) {
// No target is a magic identifier for the quit message.
return;
}
if (me.mLogging!= null) me.mLogging.println(
">>>>> Dispatching to " + msg.target + " "
+ msg.callback + ": " + msg.what
);
msg.target.dispatchMessage(msg);
if (me.mLogging!= null) me.mLogging.println(
"<<<<< Finished to " + msg.target + " "
+ msg.callback);
// Make sure that during the course of dispatching the
// identity of the thread wasn't corrupted.
final long newIdent = Binder.clearCallingIdentity();
if (ident != newIdent) {
Log.wtf("Looper", "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.recycle();
}
}
}
我们可以看出10行-42行是一个while(true)死循环,一直调用MessageQueue的next方法获取消息,该方法当没有消息的时候会处于阻塞状态。当取到消息的时候就会通过24行msg.target.dispatchMessage(msg)回调到我们在Handler的callBack或者handleMessage()方法中的代码逻辑。
另外Looper类中比较重要的方法是quit方法
public void quit() {
Message msg = Message.obtain();
// NOTE: By enqueueing directly into the message queue, the
// message is left with a null target. This is how we know it is
// a quit message.
mQueue.enqueueMessage(msg, 0);
}
note注释中也有说明,一般来说发送一个Message的动作是由一个Handler类完成的,这样一个Message对象就能对应一个Handler对象,此处没有通过handler而是将Message直接添加到MessageQueue消息链表中,会被作为Looper停止的一个标志位,这点会在MessageQueue源码分析中说明。
3. 结束语
通过Looper类的分析,可以看出Looper类的主要作用是循环取消息和分发消息,关于Message的逻辑结构此类是不关心的,关于Message的逻辑结构是在MessageQueue这个类中定义的,下一节将对MessageQueue类进行分析!