前面写了两篇源码解析了,Handler源码解析和MessageQueue源码解析,其中MessageQueue源码解析里面情况解释的不是太清晰,随着以后对代码的理解,会有后续内容的添加。
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. Most interaction with a message loop is through the Handler class. This is a typical example of the implementation of a Looper thread, using the separation of prepare() and loop() to create an initial Handler to communicate with the Looper.
类用于为一个线程运行一个消息循环。默认情况下线程没有相关联的消息循环;可以通过在线程里调用looper的prepare()方法创建一个looper,然后就会调用loop()处理消息之道loop被停止。
大多数消息是通过handler来处理。
下面是一个典型的Looper thread的实现,使用分离的准备()和循环()来创建一个Handler与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(); } }
// sThreadLocal.get() will return null unless you've called prepare(). static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>(); final MessageQueue mQueue; final Thread mThread; volatile boolean mRun; private Printer mLogging = null; private static Looper mMainLooper = null; // guarded by Looper.class
Simple interface for printing text, allowing redirection to various targets. Standard implementations are android.util.LogPrinter, android.util.StringBuilderPrinter, and android.util.PrintWriterPrinter.
看完变量,再看构造方法:
private Looper() { mQueue = new MessageQueue(); mRun = true; mThread = Thread.currentThread(); }
/** Initialize the current thread as a looper. * This gives you a chance to create handlers that then reference * this looper, before actually starting the loop. Be sure to call * {@link #loop()} after calling this method, and end it by calling * {@link #quit()}. */ public static void prepare() { if (sThreadLocal.get() != null) { throw new RuntimeException("Only one Looper may be created per thread"); } sThreadLocal.set(new Looper()); }看一下prepare类,首先它是一个静态类。为当前线程初始化一个looper,在正式启动这个loop的之前,你有机会创建一个handler和这个looper关联。在调用loop方法之前,一定要确认调用prepare方法,在最后结束的时候调用quit方法。如果这个线程已经设过了looper的话就会报错这说明,一个线程只能设一个looper。
/** * Initialize the current thread as a looper, marking it as an * application's main looper. The main looper for your application * is created by the Android environment, so you should never need * to call this function yourself. See also: {@link #prepare()} */ public static void prepareMainLooper() { prepare(); setMainLooper(myLooper()); myLooper().mQueue.mQuitAllowed = false; }
然后调用setMainLooper这个方法为mMainLooper赋值
private synchronized static void setMainLooper(Looper looper) { mMainLooper = looper; }而myLooper方法:
/** * Return the Looper object associated with the current thread. Returns * null if the calling thread is not associated with a Looper. */ public static Looper myLooper() { return sThreadLocal.get(); }
下面一个方法是获取MainLooper:
/** Returns the application's main looper, which lives in the main thread of the application. */ public synchronized static Looper getMainLooper() { return mMainLooper; }
下面是本篇代码之重点:loop方法:
/**
* Run the message queue in this thread. Be sure to call
* {@link #quit()} to end the loop.
*/
public static void loop() {
Looper me = myLooper();//获取当前looper
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}//如果为空,则抛异常
MessageQueue queue = me.mQueue;//把当前looper的queue赋值给局部变量queue
// 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();//确保当前线程属于当前进程,并且记录真实的token。
final long ident = Binder.clearCallingIdentity();
while (true) {
Message msg = queue.next(); // might block有可能会阻塞
if (msg != null) {
if (msg.target == null) {
// No target is a magic identifier for the quit message.退出消息的标示就是target为空
return;
}
long wallStart = 0;
long threadStart = 0;
// This must be in a local variable, in case a UI event sets the logger 一个局部变量,为ui事件设置log记录。
Printer logging = me.mLogging;
if (logging != null) {
logging.println(">>>>> Dispatching to " + msg.target + " " +
msg.callback + ": " + msg.what);
wallStart = SystemClock.currentTimeMicro();
threadStart = SystemClock.currentThreadTimeMicro();
}
//handler处理消息
msg.target.dispatchMessage(msg);
if (logging != null) {
long wallTime = SystemClock.currentTimeMicro() - wallStart;
long threadTime = SystemClock.currentThreadTimeMicro() - threadStart;
logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
if (logging instanceof Profiler) {
((Profiler) logging).profile(msg, wallStart, wallTime,
threadStart, threadTime);
}
}
// 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.recycle()将其放入Message Pool中。
msg.recycle();
}
}
}
/** * Control logging of messages as they are processed by this Looper. If * enabled, a log message will be written to <var>printer</var> * at the beginning and ending of each message dispatch, identifying the * target Handler and message contents. * * @param printer A Printer object that will receive log messages, or * null to disable message logging. */ public void setMessageLogging(Printer printer) { mLogging = printer; }
/** * Return the {@link MessageQueue} object associated with the current * thread. This must be called from a thread running a Looper, or a * NullPointerException will be thrown. */ public static MessageQueue myQueue() { return myLooper().mQueue; }
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); }
返回当前线程和返回当前Messagequeue:
/** * Return the Thread associated with this Looper. */ public Thread getThread() { return mThread; } /** @hide */ public MessageQueue getQueue() { return mQueue; }
public void dump(Printer pw, String prefix) { pw = PrefixPrinter.create(pw, prefix); pw.println(this.toString()); pw.println("mRun=" + mRun); pw.println("mThread=" + mThread); pw.println("mQueue=" + ((mQueue != null) ? mQueue : "(null")); if (mQueue != null) { synchronized (mQueue) { long now = SystemClock.uptimeMillis(); Message msg = mQueue.mMessages; int n = 0; while (msg != null) { pw.println(" Message " + n + ": " + msg.toString(now)); n++; msg = msg.next; } pw.println("(Total messages: " + n + ")"); } } }
/** * @hide */ public static interface Profiler { void profile(Message message, long wallStart, long wallTime, long threadStart, long threadTime); }
好,结束,可以做饭,然后重温最爱的《肖申克的救赎》了。
查看更多源码内容:Android源码解析!