在前文《Android多线程分析之二:Thread的实现》中已经具体分析了Android Thread 是怎样创建,执行以及销毁的,其重点是对对应 native 方法进行分析,今天我将聚焦于 Android Framework 层多线程相关的类:Handler, Looper, MessageQueue, Message 以及它们与Thread 之间的关系。能够用一个不太妥当的比喻来形容它们之间的关联:假设把 Thread 比作生产车间,那么 Looper 就是放在这车间里的生产线,这条生产线源源不断地从 MessageQueue 中获取材料 Messsage,并分发处理 Message (因为Message 一般是完备的,所以 Looper 大多数情况下仅仅是调度让 Message 的 Handler 去处理 Message)。正是因为消息须要在 Looper 中处理,而 Looper 又需执行在 Thread 中,所以不能随随便便在非 UI 线程中进行 UI 操作。 UI 操作一般会通过投递消息来实现,仅仅有往正确的 Looper 投递消息才干得到处理,对于 UI 来说,这个 Looper 一定是执行在 UI 线程中。
在编写 app 的过程中,我们经常会这样来使用 Handler:
Handler mHandler = new Handler(); mHandler.post(new Runnable(){ @Override public void run() { // do somework } });或者如这系列文章第一篇中的演示样例那样:
private Handler mHandler= new Handler(){ @Override public void handleMessage(Message msg) { Log.i("UI thread", " >> handleMessage()"); switch(msg.what){ case MSG_LOAD_SUCCESS: Bitmap bitmap = (Bitmap) msg.obj; mImageView.setImageBitmap(bitmap); mProgressBar.setProgress(100); mProgressBar.setMessage("Image downloading success!"); mProgressBar.dismiss(); break; case MSG_LOAD_FAILURE: mProgressBar.setMessage("Image downloading failure!"); mProgressBar.dismiss(); break; } } }; Message msg = mHandler.obtainMessage(MSG_LOAD_FAILURE, null); mHandler.sendMessage(msg);
final MessageQueue mQueue; final Looper mLooper; final Callback mCallback; final boolean mAsynchronous; public Handler(Looper looper, Callback callback, boolean async) { mLooper = looper; mQueue = looper.mQueue; mCallback = callback; mAsynchronous = async; } public Handler(Callback callback, boolean async) { mLooper = Looper.myLooper(); if (mLooper == null) { throw new RuntimeException( "Can't create handler inside thread that has not called Looper.prepare()"); } mQueue = mLooper.mQueue; mCallback = callback; mAsynchronous = async; } public Handler() { this(null, false); }
mLooper:线程的消息处理循环,注意:并不是每个线程都有消息处理循环,因此 Framework 中线程能够分为两种:有 Looper 的和无 Looper 的。为了方便 app 开发,Framework 提供了一个有 Looper 的 Thread 实现:HandlerThread。在前一篇《Thread的实现》中也提到了两种不同 Thread 的 run() 方法的差别。
/** * Handy class for starting a new thread that has a looper. The looper can then be * used to create handler classes. Note that start() must still be called. */ public class HandlerThread extends Thread { Looper mLooper; /** * Call back method that can be explicitly overridden if needed to execute some * setup before Looper loops. */ protected void onLooperPrepared() { } public void run() { mTid = Process.myTid(); Looper.prepare(); synchronized (this) { mLooper = Looper.myLooper(); notifyAll(); } Process.setThreadPriority(mPriority); onLooperPrepared(); Looper.loop(); mTid = -1; } /** * This method returns the Looper associated with this thread. If this thread not been started * or for any reason is isAlive() returns false, this method will return null. If this thread * has been started, this method will block until the looper has been initialized. * @return The looper. */ public Looper getLooper() { if (!isAlive()) { return null; } // If the thread has been started, wait until the looper has been created. synchronized (this) { while (isAlive() && mLooper == null) { try { wait(); } catch (InterruptedException e) { } } } return mLooper; } }
/** 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() { 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)); }
/** * 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(); }
Handler 的成员变量 mQueue 是其成员变量 mLooper 的成员变量,这里仅仅是为了简化书写,单独拿出来作为 Handler 的成员变量;成员变量 mCallback 提供了还有一种使用Handler 的简便途径:仅仅需实现回调接口 Callback,而无需子类化Handler,以下会讲到的:
/** * Callback interface you can use when instantiating a Handler to avoid * having to implement your own subclass of Handler. */ public interface Callback { public boolean handleMessage(Message msg); }
同是否有无 Looper 来区分 Thread 一样,Handler 的构造函数也分为自带 Looper 和外部 Looper 两大类:假设提供了 Looper,在消息会在该 Looper 中处理,否则消息就会在当前线程的 Looper 中处理,注意这里要确保当前线程一定有 Looper。全部的 UI thread 都是有 Looper 的,因为 view/widget 的实现中大量使用了消息,须要 UI thread 提供 Looper 来处理,能够參考view.java:
view.java public boolean post(Runnable action) { final AttachInfo attachInfo = mAttachInfo; if (attachInfo != null) { return attachInfo.mHandler.post(action); } // Assume that post will succeed later ViewRootImpl.getRunQueue().post(action); return true; } ViewRootImpl.java private void performTraversals() { .... // Execute enqueued actions on every traversal in case a detached view enqueued an action getRunQueue().executeActions(attachInfo.mHandler); ... } static RunQueue getRunQueue() { RunQueue rq = sRunQueues.get(); if (rq != null) { return rq; } rq = new RunQueue(); sRunQueues.set(rq); return rq; } /** * The run queue is used to enqueue pending work from Views when no Handler is * attached. The work is executed during the next call to performTraversals on * the thread. * @hide */ static final class RunQueue { ... void executeActions(Handler handler) { synchronized (mActions) { final ArrayList<HandlerAction> actions = mActions; final int count = actions.size(); for (int i = 0; i < count; i++) { final HandlerAction handlerAction = actions.get(i); handler.postDelayed(handlerAction.action, handlerAction.delay); } actions.clear(); } } }
public final class ActivityThread { ... final Looper mLooper = Looper.myLooper(); }
void checkThread() { if (mThread != Thread.currentThread()) { throw new CalledFromWrongThreadException( "Only the original thread that created a view hierarchy can touch its views."); } }
W/dalvikvm(796): threadid=11: thread exiting with uncaught exception (group=0x40a71930) E/AndroidRuntime(796): FATAL EXCEPTION: Thread-75 E/AndroidRuntime(796): android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views. E/AndroidRuntime(796): at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:4746) E/AndroidRuntime(796): at android.view.ViewRootImpl.requestLayout(ViewRootImpl.java:823) E/AndroidRuntime(796): at android.view.View.requestLayout(View.java:15473) E/AndroidRuntime(796): at android.view.View.requestLayout(View.java:15473) E/AndroidRuntime(796): at android.view.View.requestLayout(View.java:15473) E/AndroidRuntime(796): at android.view.View.requestLayout(View.java:15473) E/AndroidRuntime(796): at android.view.View.requestLayout(View.java:15473) E/AndroidRuntime(796): at android.widget.ImageView.setImageDrawable(ImageView.java:406) E/AndroidRuntime(796): at android.widget.ImageView.setImageBitmap(ImageView.java:421) E/AndroidRuntime(796): at com.example.thread01.MainActivity$2$1.run(MainActivity.java:80)
/** * Subclasses must implement this to receive messages. */ public void handleMessage(Message msg) { } /** * Handle system messages here. */ public void dispatchMessage(Message msg) { if (msg.callback != null) { handleCallback(msg); } else { if (mCallback != null) { if (mCallback.handleMessage(msg)) { return; } } handleMessage(msg); } }
private static void handleCallback(Message message) { message.callback.run(); }
在分析 Looper::Loop() 这个关键函数之前,先来理一理 Thread,Looper,Handler,MessageQueue 的关系:Thread 须要有 Looper 才干处理消息(也就是说 Looper 是执行在 Thread 中),这是通过在自己定义 Thread 的 run() 函数中调用 Looper::prepare() 和 Looper::loop() 来实现,然后在 Looper::loop() 中不断地从 MessageQueue 获取由 Handler 投递到当中的 Message,并调用 Message 的成员变量 Handler 的 dispatchMessage 来处理消息。
以下先来看看 Looper 的构造函数:
final MessageQueue mQueue; final Thread mThread; volatile boolean mRun; private Looper(boolean quitAllowed) { mQueue = new MessageQueue(quitAllowed); mRun = true; mThread = Thread.currentThread(); }
/** * 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(false); synchronized (Looper.class) { if (sMainLooper != null) { throw new IllegalStateException("The main Looper has already been prepared."); } sMainLooper = myLooper(); } }
SystemServer.java 中的 ServerThread,ServerThread 的重要性就不用说了,绝大部分 Android Service 都是这个线程中初始化的。这个线程是在 Android 启动过程中的 init2() 方法启动的:
public static final void init2() { Slog.i(TAG, "Entered the Android system server!"); Thread thr = new ServerThread(); thr.setName("android.server.ServerThread"); thr.start(); } class ServerThread extends Thread { @Override public void run() { ... Looper.prepareMainLooper(); ... Looper.loop(); Slog.d(TAG, "System ServerThread is exiting!"); } }
public static void main(String[] args) { .... Looper.prepareMainLooper(); ActivityThread thread = new ActivityThread(); thread.attach(false); if (sMainThreadHandler == null) { sMainThreadHandler = thread.getHandler(); } AsyncTask.init(); Looper.loop(); throw new RuntimeException("Main thread loop unexpectedly exited"); }
有了前面的铺垫,这下我们就能够来分析 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; ... 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.recycle(); } }