1.1 Looper
位置:
/frameworks/base/core/java/android/os/Looper.java
Looper:循环者的意思,他被设计用来将一个普通线程变成Looper线程,即循环工作的线程。
/* 56 * API Implementation Note: 57 * 58 * This class contains the code required to set up and manage an event loop 59 * based on MessageQueue. APIs that affect the state of the queue should be 60 * defined on MessageQueue or Handler rather than on Looper itself. For example, 61 * idle handlers and sync barriers are defined on the queue whereas preparing the 62 * thread, looping, and quitting are defined on the looper. 63 */
|
Looper类基于MessageQueue(消息队列)来管理一个循环事件。并且这个消息队列的状态是在MessageQueue(消息队列)或者Handler中设置和更改的,并不是在Looper中。也就是说,Looper通过一个由其他类控制的MessageQueue来维持循环。其中MessageQueue已经封装到了Looper中,对于开发者来说,MessageQueue是透明的,直接操作的是Message。
如何是一个正常的线程变成Looper线程:
public class LooperThread extends Thread { @Override public void run() { // 将当前线程初始化为Looper线程 Looper.prepare();
// ...其他处理,如实例化handler
// 开始循环处理消息队列 Looper.loop(); } } |
通过两行核心代码,普通线程就会变成Looper线程。
Looper.prepare()
Looper.loop()
通过Looper.prepare(),线程中就会出现一个Looper的对象,它内部维护一个消息队列,并且通过prepare()源码我们发现,一个线程只能对应一个Looper对象。
其实,将普通线程,变成Looper线程比较简单。接下来,我们看下Looper的源码,分析下它的实现。
// sThreadLocal.get() will return null unless you've called prepare(). 68 static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>(); //每个线程只能有一个Looper对象 69 private static Looper sMainLooper; // guarded by Looper.class 70 71 final MessageQueue mQueue; //消息队列 72 final Thread mThread; //当前线程 73 74 private Printer mLogging;
|
每个线程中的Looper对象其实就是一个ThreadLocal,即线程本地存储(TLS)对象。
/** Initialize the current thread as a looper. 77 * This gives you a chance to create handlers that then reference 78 * this looper, before actually starting the loop. Be sure to call 79 * {@link #loop()} after calling this method, and end it by calling 80 * {@link #quit()}. 81 */ 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"); } sThreadLocal.set(new Looper(quitAllowed)); }
|
prepare(BooleanquitAllowed);方法是利用TLS来产生Looper对象。
private Looper(boolean quitAllowed) { mQueue = new MessageQueue(quitAllowed); mThread = Thread.currentThread(); //Looper的Thread指向的是当前的线程 }
|
Looper的构造方法。
生成MessageQueue;
mThread指向当前线程;
Looper中的主循环,loop(循环),知道quit()后执行终止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(); //得到当前线程Looper if (me == null) { throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread."); } //得到当前Looper的MQ(消息队列) 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. //确定该线程是属于本地进程,不影响Looper理解 Binder.clearCallingIdentity(); final long ident = Binder.clearCallingIdentity(); for (;;) { //开始循环 Message msg = queue.next(); // might block if (msg == null) { // No message indicates that the message queue is quitting. return; } //日志内容 // This must be in a local variable, in case a UI event sets the logger Printer logging = me.mLogging; if (logging != null) { logging.println(">>>>> Dispatching to " + msg.target + " " + msg.callback + ": " + msg.what); } //重要,真正的处理工作借给Message的target,即handler msg.target.dispatchMessage(msg); if (logging != null) { logging.println("<<<<< Finished to " + msg.target + " " + msg.callback); } //ID处理 // 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(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); } //回收Message资源 msg.recycleUnchecked(); } } |
当Looper调用loop()后,looper线程开始真正的工作。
Looper的其他函数:
myLooper()//获取当前Looper
public static @Nullable Looper myLooper() { return sThreadLocal.get(); } |
//getMainLooper()获取application中的主线程的looper
/** * Returns the application's main looper, which lives in the main thread of the application. */ public static Looper getMainLooper() { synchronized (Looper.class) { return sMainLooper; } } |
quit()函数;
//一些消息可能还没有提交,在loop处理结束之前
public void quit() { mQueue.quit(false); } |
//所有消息都处理结束,并且没有新的消息提交
public void quitSafely() { mQueue.quit(true); } |
其中android中的Actvity也为一个Looper线程。
Looper 循环者,它设计是用来是一个普通线程变成Looper线程。主要作用是使一个线程不断循环,一旦有新任务则完成新任务,之后继续循环等待下一个任务。
总结:
1.每个线程有且最多只能有一个Looper对象,它是一个ThreadLocal
2.Looper内部有一个消息队列,loop()方法调用后线程开始不断从队列中取出消息执行
3.Looper使一个线程变成Looper线程。