一、Looper
Looper
对象,顾名思义,直译过来就是循环的意思,从MessageQueue中不断取出message。
Class used to run a message loop for a thread. Threads by default do not have a message loop associated with them; to create one, call prepare() in the thread that is to run the loop, and then loop() to have it process messages until the loop is stopped.
1.Looper的成员变量:
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>(); private static Looper sMainLooper; // guarded by Looper.class final MessageQueue mQueue; //一个MQ final Thread mThread; //一个thread
Looper的代码是非常简单的。在官方文档的注释中,它推荐我们这样来使用它:
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(); } }
先看看prepare方法。
Looper.prepare
public static void prepare() { prepare(true); } private static void prepare(boolean quitAllowed) { if (sThreadLocal.get() != null) {//每个线程只能有一个looper throw new RuntimeException("Only one Looper may be created per thread"); } //设置本线程的looper。 sThreadLocal.set(new Looper(quitAllowed)); }
注意prepare(boolean)
方法中,有一个sThreadLocal
变量(ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本),这个变量有点像一个哈希表,它的key是当前的线程,也就是说,它可以存储一些数据/引用,这些数据/引用是与当前线程是一一对应的,在这里的作用是,它判断一下当前线程是否有Looper
这个对象,如果有,那么就报错了,"Only one Looper may be created per thread",一个线程只允许创建一个Looper
,如果没有,就new一个。然后它调用了Looper
的构造方法。
Looper 的构造方法
在上边调用了构造方法:Looper(quitAllowed),初始化了messageQueue并绑定当前线程。
private Looper(boolean quitAllowed) { mQueue = new MessageQueue(quitAllowed); mThread = Thread.currentThread(); }
此时的初始化动作已经结束了,接下来看Looper.loop():
public static void loop() { final Looper me = myLooper();//返回当前的looper if (me == null) { throw new RuntimeException("No Looper; Looper.prepare() wasn‘t called on this thread."); } final MessageQueue queue = me.mQueue;//取得messageQueue for (;;) { Message msg = queue.next(); // might block if (msg == null) { // No message indicates that the message queue is quitting. return; } 。。。。 msg.target.dispatchMessage(msg); 。。。 msg.recycleUnchecked(); } }
loop()方法,省去了一些不关心的部分。剩下的部分非常的清楚了,首先调用了静态方法myLooper()获取当前Looper对象。没有looper则抛出异常。
public static @Nullable Looper myLooper() { return sThreadLocal.get(); }
1. myLooper()
同样是静态方法,它是直接从这个ThreadLocal
中去获取Looper对象,拿到当前线程的Looper
后;
2. MessageQueue queue = me.mQueue;
拿到与这个Looper
对应的MQ,就开始无限循环,不断的从消息队列中取出Message,当获取到一个消息后,它调用了Message.target.dispatchMessage()
方法来对消息进行处理。dispatchMessage这个方法在Handler中,就是处理message。
3.msg.recycleUnchecked(),当这个msg处理完了,就没有用啦,把它回收到全局池中,注意不是销毁。
总结
Looper的代码看完了,我们得到了几个信息:
Looper
调用静态方法prepare()
来进行初始化,一个线程只能创建一个与之对应的Looper
,Looper
初始化的时候会创建一个MQ,并和当前线程绑定,因此,有了这样的对应关系,一个线程对应一个Looper
,一个Looper
对应一个MQ。Looper
调用静态方法loop()
开始无限循环的取消息,messageQueue调用next()
方法来获取消息(这也是个无限循环)。
MessageQueue源码解析:http://www.cnblogs.com/jycboy/p/5786682.html
Message源码解析:http://www.cnblogs.com/jycboy/p/5786551.html