android的消息队列机制


android下的线程,Looper线程,MessageQueue,Handler,Message等之间的关系,以及Message的send/post及Message dispatch的过程。

Looper线程

我们知道,线程是进程中某个单一顺序的控制流,它是内核做CPU调度的单位。那何为Looper线程呢?所谓Looper线程,即是借助于Looper和MessageQueue来管理控制流的一类线程。在android系统中,application的主线程即是借助于Looper和MessageQueue来管理控制流的。其实,不仅仅只有主线程可以用Looper和MessageQueue来管理控制流,其他的线程也一样可以。我们可以先看一下android source code的注释中给出的一种Looper线程的实现方式:

01package com.example.messagequeuedemo;
02 
03import android.os.Handler;
04import android.os.Looper;
05import android.util.Log;
06 
07public class LooperThread extends Thread {
08    public static final String TAG = MainActivity.TAG;
09    private static final String CompTAG = "<span></span>LooperThread<span></span>";
10 
11    public Handler mHandler;
12 
13    @Override
14    public void run() {
15        Log.d(TAG, CompTAG + ": LooperThread=>run");
16        Looper.prepare();
17 
18        mHandler = new Handler() {
19            public void handleMessage(android.os.Message msg) {
20                Log.d(TAG, CompTAG + ": LooperThread=>Handler=>handleMessage");
21                // process incoming message here
22            }
23        };
24 
25        Looper.loop();
26    }
27}

可以看到,就是在线程的run()方法中,调用Looper.prepare()做一些初始化,然后创建一个Handler对象,最后执行Looper.loop()即开始了整个的事件循环。就是这么的简单,一个可以使用消息队列来管理线程执行流程的Looper 线程就创建好了。

接着我们来看一下,神秘的Looper.prepare()到底都干了些什么事情:

01// sThreadLocal.get() will return null unless you've called prepare().
02 static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
03 
04/** Initialize the current thread as a looper.
05  * This gives you a chance to create handlers that then reference
06  * this looper, before actually starting the loop. Be sure to call
07  * {@link #loop()} after calling this method, and end it by calling
08  * {@link #quit()}.
09  */
10public static void prepare() {
11    prepare(true);
12}
13 
14private static void prepare(boolean quitAllowed) {
15    if (sThreadLocal.get() != null) {
16        throw new RuntimeException("Only one Looper may be created per thread");
17    }
18    sThreadLocal.set(new Looper(quitAllowed));
19}
20 
21 
22private Looper(boolean quitAllowed) {
23    mQueue = new MessageQueue(quitAllowed);
24    mRun = true;
25    mThread = Thread.currentThread();
26}

可以看到,它做的事情就是为当前的线程创建了一个Looper对象,并存储在一个静态的线程局部变量中。在Looper的构造函数中创建了MessageQueue,同时Looper会引用到当前的线程,并将一个表示状态的变量mRun设置为true。对于此处的线程局部变量sThreadLocal,可以理解为就是一个HashMap,该HashMap中存放的数据其类型为Looper,而HashMap的key则Thread.currentThread()。

启动Looper线程就和启动普通的线程一样,比如:

01public class MainActivity extends Activity {
02    public static final String TAG = "MessageQueueDemo";
03    private static final String CompTAG = "MainActivity";
04    private LooperThread mLooperThread;
05 
06    @Override
07    protected void onCreate(Bundle savedInstanceState) {
08        Log.d(TAG, CompTAG + ": MainActivity=>onCreate");
09        super.onCreate(savedInstanceState);
10        setContentView(R.layout.activity_main);
11 
12        mLooperThread = new LooperThread();
13        mLooperThread.start();
14    }

同样是new一个Thread对象,然后执行该对象的start()方法。

其实Looper线程有两种,一种就是我们上面看到的那种普通的Looper线程,另外一种则是main loop线程,创建前者使用我们前面看到的Looper.prepare()方法,而要创建后者,我们则可以使用Looper.prepareMainLooper()方法。可以看一下Looper.prepareMainLooper()的实现:

01/**
02 * Initialize the current thread as a looper, marking it as an
03 * application's main looper. The main looper for your application
04 * is created by the Android environment, so you should never need
05 * to call this function yourself.  See also: {@link #prepare()}
06 */
07public static void prepareMainLooper() {
08    prepare(false);
09    synchronized (Looper.class) {
10        if (sMainLooper != null) {
11            throw new IllegalStateException("The main Looper has already been prepared.");
12        }
13        sMainLooper = myLooper();
14    }
15}

比较特别的地方即在于,此处调用prepare()方法传进去的参数为false,即表示这个Looper不能够被quit掉。其他倒是基本一样。整个android系统中,调用到prepareMainLooper()方法的大概有两处:

1/frameworks/base/services/java/com/android/server/
2H A D   SystemServer.java   94 Looper.prepareMainLooper();
3/frameworks/base/core/java/android/app/
4H A D   ActivityThread.java 5087 Looper.prepareMainLooper();

一处在ServerThread的run()方法中,用于为system server主线程初始化消息队列等,另外一处在ActivityThread的run()方法中,自然即是创建android app主线程的消息队列了。

通过消息与Looper线程交互

那Looper线程的特别之处究竟在哪里呢?如前所述,这种线程有一个Looper与之关联,这种线程会使用消息队列,或者称为事件循环来管理执行的流程。那这种特别之处又如何体现呢?其他线程可以向此类线程中丢消息进来,当然此类线程本身也可以往自己的消息队列里面丢消息,然后在事件循环中,这种事件会得到有效的处理。那究竟要如何往Looper线程的消息队列中发送消息呢?

回忆我们前面创建Looper线程的那个code,我们不是有创建出来一个Handler嘛。没错,我们就是通过Handler来向Looper线程的MessageQueue中发送消息的。可以看一下code的写法。先是LooperThread的写法:

01package com.intel.helloworld;
02 
03import android.os.Handler;
04import android.os.Looper;
05import android.os.Message;
06import android.util.Log;
07 
08public class LooperThread extends Thread {
09    private static final String TAG = MainActivity.TAG;
10    private static final String CompTAG = "LooperThread";
11    public Handler mHandler;
12 
13    @Override
14    public void run() {
15        Log.d(TAG, CompTAG + ": " + "LooperThread-->run");
16        Looper.prepare();
17 
18        mHandler = new Handler() {
19            @Override
20            public void handleMessage(Message msg) {
21                // process incoming message
22                Log.d(TAG, CompTAG + ": " + "Handler-->handleMessage, msg.what = " + msg.what);
23            }
24        };
25 
26        Looper.loop();
27    }
28 
29    public Handler getHandler() {
30        return mHandler;
31    }
32}

然后是向Looper线程发送消息的部分的写法:

01package com.intel.helloworld;
02 
03import android.os.Bundle;
04import android.os.Handler;
05import android.os.Message;
06import android.app.Activity;
07import android.util.Log;
08import android.view.Menu;
09 
10public class MainActivity extends Activity {
11    public static final String TAG = "LifecycleDemoApp";
12    private static final String CompTAG = "MainActivity";
13     
14    public static final int MESSAGE_WHAT_CREATE = 1;
15    public static final int MESSAGE_WHAT_START = 2;
16    public static final int MESSAGE_WHAT_RESUME = 3;
17    public static final int MESSAGE_WHAT_PAUSE = 4;
18    public static final int MESSAGE_WHAT_STOP = 5;
19    public static final int MESSAGE_WHAT_DESTROY = 6;
20 
21    LooperThread mThread;
22 
23    @Override
24    protected void onCreate(Bundle savedInstanceState) {
25        Log.d(TAG, CompTAG + ": " + "Activity-->onCreate");
26        super.onCreate(savedInstanceState);
27        setContentView(R.layout.activity_main);
28 
29        mThread = new LooperThread();
30        mThread.start();
31    }
32 
33    @Override
34    protected void onStart() {
35        Log.d(TAG, CompTAG + ": " + "Activity-->onStart");
36        super.onStart();
37 
38        Handler handler = mThread.mHandler;
39        Message msg = Message.obtain();
40        msg.what = MESSAGE_WHAT_START;
41        handler.sendMessage(msg);
42    }
43     
44    @Override
45    protected void onResume() {
46        Log.d(TAG, CompTAG + ": " + "Activity-->onResume");
47        super.onResume();
48 
49        Handler handler = mThread.mHandler;
50        Message msg = Message.obtain();
51        msg.what = MESSAGE_WHAT_RESUME;
52        handler.sendMessage(msg);
53    }
54     
55    @Override
56    protected void onPause() {
57        Log.d(TAG, CompTAG + ": " + "Activity-->onPause");
58        super.onPause();
59 
60        Handler handler = mThread.mHandler;
61        Message msg = Message.obtain();
62        msg.what = MESSAGE_WHAT_PAUSE;
63        handler.sendMessage(msg);
64    }
65     
66    @Override
67    protected void onStop() {
68        Log.d(TAG, CompTAG + ": " + "Activity-->onStop");
69        super.onStop();
70 
71        Handler handler = mThread.mHandler;
72        Message msg = Message.obtain();
73        msg.what = MESSAGE_WHAT_STOP;
74        handler.sendMessage(msg);
75    }
76 
77    @Override
78    protected void onDestroy() {
79        Log.d(TAG, CompTAG + ": " + "Activity-->onDestroy");
80        super.onDestroy();
81 
82        Handler handler = mThread.mHandler;
83        Message msg = Message.obtain();
84        msg.what = MESSAGE_WHAT_DESTROY;
85        handler.sendMessage(msg);
86    }
87 
88    @Override<span style="color: rgb(229, 51, 51);"></span> public boolean onCreateOptionsMenu(Menu menu) {
89        // Inflate the menu; this adds items to the action bar if it is present.
90        getMenuInflater().inflate(R.menu.main, menu);
91        return true;
92    }
93 
94    @Override
95    protected void onSaveInstanceState(Bundle outState) {
96        Log.d(TAG, CompTAG + ": " + "Activity-->onSaveInstanceState");
97        super.onSaveInstanceState(outState);
98    }
99}

向一个Looper线程发送消息的过程,基本上即是,调用Message.obtain()或Handler.obtainMessage()获取一个Message对象->设置Message->调用 Looper线程中创建的Handler对象来发送消息。

Handler究竟是如何知道要向哪个MessageQueue中发送消息呢,从前面的code中,我们找不到任何将Handler与特定的MessageQueue关联起来的代码,这究竟是怎么回事呢?这也是我们强调要使用Looper线程中创建的Handler对象来向该Looper线程中发送消息的原因。我们可以看一下Handler对象构造的过程:

001/**
002 * Default constructor associates this handler with the {@link Looper} for the
003 * current thread.
004 *
005 * If this thread does not have a looper, this handler won't be able to receive messages
006 * so an exception is thrown.
007 */
008public Handler() {
009    this(null, false);
010}
011 
012/**
013 * Constructor associates this handler with the {@link Looper} for the
014 * current thread and takes a callback interface in which you can handle
015 * messages.
016 *
017 * If this thread does not have a looper, this handler won't be able to receive messages
018 * so an exception is thrown.
019 *
020 * @param callback The callback interface in which to handle messages, or null.
021 */
022public Handler(Callback callback) {
023    this(callback, false);
024}
025 
026/**
027 * Use the provided {@link Looper} instead of the default one.
028 *
029 * @param looper The looper, must not be null.
030 */
031public Handler(Looper looper) {
032    this(looper, null, false);
033}
034 
035/**
036 * Use the provided {@link Looper} instead of the default one and take a callback
037 * interface in which to handle messages.
038 *
039 * @param looper The looper, must not be null.
040 * @param callback The callback interface in which to handle messages, or null.
041 */
042public Handler(Looper looper, Callback callback) {
043    this(looper, callback, false);
044}
045 
046/**
047 * Use the {@link Looper} for the current thread
048 * and set whether the handler should be asynchronous.
049 *
050 * Handlers are synchronous by default unless this constructor is used to make
051 * one that is strictly asynchronous.
052 *
053 * Asynchronous messages represent interrupts or events that do not require global ordering
054 * with represent to synchronous messages.  Asynchronous messages are not subject to
055 * the synchronization barriers introduced by {@link MessageQueue#enqueueSyncBarrier long)}.
056 *
057 * @param async If true, the handler calls {@link Message#setAsynchronous(boolean)} for
058 * each {@link Message} that is sent to it or {@link Runnable} that is posted to it.
059 *
060 * @hide
061 */
062public Handler(boolean async) {
063    this(null, async);
064}
065 
066/**
067 * Use the {@link Looper} for the current thread with the specified callback interface
068 * and set whether the handler should be asynchronous.
069 *
070 * Handlers are synchronous by default unless this constructor is used to make
071 * one that is strictly asynchronous.
072 *
073 * Asynchronous messages represent interrupts or events that do not require global ordering
074 * with represent to synchronous messages.  Asynchronous messages are not subject to
075 * the synchronization barriers introduced by {@link MessageQueue#enqueueSyncBarrier long)}.
076 *
077 * @param callback The callback interface in which to handle messages, or null.
078 * @param async If true, the handler calls {@link Message#setAsynchronous(boolean)} for
079 * each {@link Message} that is sent to it or {@link Runnable} that is posted to it.
080 *
081 * @hide
082 */
083public Handler(Callback callback, boolean async) {
084    if (FIND_POTENTIAL_LEAKS) {
085        final Class<? extends Handler> klass = getClass();
086        if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
087                (klass.getModifiers() & Modifier.STATIC) == 0) {
088            Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
089                klass.getCanonicalName());
090        }
091    }
092 
093    mLooper = Looper.myLooper();
094    if (mLooper == null) {
095        throw new RuntimeException(
096            "Can't create handler inside thread that has not called Looper.prepare()");
097    }
098    mQueue = mLooper.mQueue;
099    mCallback = callback;
100    mAsynchronous = async;
101}

可以看到,很简单,是通过Looper.myLooper()获取到当前线程的Looper对象,并与相关的MessageQueue等关联起来的。这也是前面我们在实现Looper线程时,要在其run方法中创建一个public的Handler的依据。当然,我们也可以在构造Handler对象时,显式地使其与特定的Looper对象关联起来。

Handler提供了两组函数用于向一个Looper线程的MessageQueue中发送消息,分别是postXXX()族和sendXXX()族。可以先看一下sendXXX()族的实现:

001/**
002 * Pushes a message onto the end of the message queue after all pending messages
003 * before the current time. It will be received in {@link #handleMessage},
004 * in the thread attached to this handler.
005 
006 * @return Returns true if the message was successfully placed in to the
007 *         message queue.  Returns false on failure, usually because the
008 *         looper processing the message queue is exiting.
009 */
010public final boolean sendMessage(Message msg)
011{
012    return sendMessageDelayed(msg, 0);
013}
014 
015/**
016 * Sends a Message containing only the what value.
017 
018 * @return Returns true if the message was successfully placed in to the
019 *         message queue.  Returns false on failure, usually because the
020 *         looper processing the message queue is exiting.
021 */
022public final boolean sendEmptyMessage(int what)
023{
024    return sendEmptyMessageDelayed(what, 0);
025}
026 
027/**
028 * Sends a Message containing only the what value, to be delivered
029 * after the specified amount of time elapses.
030 * @see #sendMessageDelayed(android.os.Message, long)
031 *
032 * @return Returns true if the message was successfully placed in to the
033 *         message queue.  Returns false on failure, usually because the
034 *         looper processing the message queue is exiting.
035 */
036public final boolean sendEmptyMessageDelayed(int what, long delayMillis) {
037    Message msg = Message.obtain();
038    msg.what = what;
039    return sendMessageDelayed(msg, delayMillis);
040}
041 
042/**
043 * Sends a Message containing only the what value, to be delivered
044 * at a specific time.
045 * @see #sendMessageAtTime(android.os.Message, long)
046 
047 * @return Returns true if the message was successfully placed in to the
048 *         message queue.  Returns false on failure, usually because the
049 *         looper processing the message queue is exiting.
050 */
051 
052public final boolean sendEmptyMessageAtTime(int what, long uptimeMillis) {
053    Message msg = Message.obtain();
054    msg.what = what;
055    return sendMessageAtTime(msg, uptimeMillis);
056}
057 
058/**
059 * Enqueue a message into the message queue after all pending messages
060 * before (current time + delayMillis). You will receive it in
061 * {@link #handleMessage}, in the thread attached to this handler.
062 
063 * @return Returns true if the message was successfully placed in to the
064 *         message queue.  Returns false on failure, usually because the
065 *         looper processing the message queue is exiting.  Note that a
066 *         result of true does not mean the message will be processed -- if
067 *         the looper is quit before the delivery time of the message
068 *         occurs then the message will be dropped.
069 */
070public final boolean sendMessageDelayed(Message msg, long delayMillis)
071{
072    if (delayMillis < 0) {
073        delayMillis = 0;
074    }
075    return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
076}
077 
078/**
079 * Enqueue a message into the message queue after all pending messages
080 * before the absolute time (in milliseconds) <var>uptimeMillis</var>.
081 * <b>The time-base is {@link android.os.SystemClock#uptimeMillis}.</b>
082 * You will receive it in {@link #handleMessage}, in the thread attached
083 * to this handler.
084 *
085 * @param uptimeMillis The absolute time at which the message should be
086 *         delivered, using the
087 *         {@link android.os.SystemClock#uptimeMillis} time-base.
088 *        
089 * @return Returns true if the message was successfully placed in to the
090 *         message queue.  Returns false on failure, usually because the
091 *         looper processing the message queue is exiting.  Note that a
092 *         result of true does not mean the message will be processed -- if
093 *         the looper is quit before the delivery time of the message
094 *         occurs then the message will be dropped.
095 */
096public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
097    MessageQueue queue = mQueue;
098    if (queue == null) {
099        RuntimeException e = new RuntimeException(
100                this + " sendMessageAtTime() called with no mQueue");
101        Log.w("Looper", e.getMessage(), e);
102        return false;
103    }
104    return enqueueMessage(queue, msg, uptimeMillis);
105}
106 
107/**
108 * Enqueue a message at the front of the message queue, to be processed on
109 * the next iteration of the message loop.  You will receive it in
110 * {@link #handleMessage}, in the thread attached to this handler.
111 * <b>This method is only for use in very special circumstances -- it
112 * can easily starve the message queue, cause ordering problems, or have
113 * other unexpected side-effects.</b>
114 
115 * @return Returns true if the message was successfully placed in to the
116 *         message queue.  Returns false on failure, usually because the
117 *         looper processing the message queue is exiting.
118 */
119public final boolean sendMessageAtFrontOfQueue(Message msg) {
120    MessageQueue queue = mQueue;
121    if (queue == null) {
122        RuntimeException e = new RuntimeException(
123            this + " sendMessageAtTime() called with no mQueue");
124        Log.w("Looper", e.getMessage(), e);
125        return false;
126    }
127    return enqueueMessage(queue, msg, 0);
128}
129 
130private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
131    msg.target = this;
132    if (mAsynchronous) {
133        msg.setAsynchronous(true);
134    }
135    return queue.enqueueMessage(msg, uptimeMillis);
136}

绕来绕去,最终都是调用MessageQueue的enqueueMessage()方法来将一个Message放入一个MessageQueue中。值得注意的是,在Handler.enqueueMessage()中,会将Message的target设置为this,这实际上是决定了Looper的消息循环中,在dispatch/handle message时将会使用的Handler。即,在default情况下,处理message的那个handler也将会是发送此message的handler。

Handler实际的职责,并不像它的名称所显示的那样,其实它不仅仅是处理message,它还负责发送Message给线程的MessageQueue。

再来看一下MessageQueue的enqueueMessage()方法的code:

01boolean enqueueMessage(Message msg, long when) {
02    if (msg.isInUse()) {
03        throw new AndroidRuntimeException(msg + " This message is already in use.");
04    }
05    if (msg.target == null) {
06        throw new AndroidRuntimeException("Message must have a target.");
07    }
08 
09    boolean needWake;
10    synchronized (this) {
11        if (mQuiting) {
12            RuntimeException e = new RuntimeException(
13                    msg.target + " sending message to a Handler on a dead thread");
14            Log.w("MessageQueue", e.getMessage(), e);
15            return false;
16        }
17 
18        msg.when = when;
19        Message p = mMessages;
20        if (p == null || when == 0 || when < p.when) {
21            // New head, wake up the event queue if blocked.
22            msg.next = p;
23            mMessages = msg;
24            needWake = mBlocked;
25        } else {
26            // Inserted within the middle of the queue.  Usually we don't have to wake
27            // up the event queue unless there is a barrier at the head of the queue
28            // and the message is the earliest asynchronous message in the queue.
29            needWake = mBlocked && p.target == null && msg.isAsynchronous();
30            Message prev;
31            for (;;) {
32                prev = p;
33                p = p.next;
34                if (p == null || when < p.when) {
35                    break;
36                }
37                if (needWake && p.isAsynchronous()) {
38                    needWake = false;
39                }
40            }
41            msg.next = p; // invariant: p == prev.next
42            prev.next = msg;
43        }
44    }
45    if (needWake) {
46        nativeWake(mPtr);
47    }
48    return true;
49}

整个将Message放入MessageQueue的算法也还算比较清晰简洁,并没有什么太绕的地方。此处我们可以一览MessageQueue中保存Messages的结构,即,MessageQueue用一个单向链表来保存所有的Message,而链表中各个Message则按照其请求的执行时间先后来排列。

向Looper 线程的MessageQueue中发送消息的另外一族方法postXXX(),其实现同前面的sendXXX()族方法也大同小异啦:

01/**
02 * Causes the Runnable r to be added to the message queue.
03 * The runnable will be run on the thread to which this handler is
04 * attached.
05 *
06 * @param r The Runnable that will be executed.
07 *
08 * @return Returns true if the Runnable was successfully placed in to the
09 *         message queue.  Returns false on failure, usually because the
10 *         looper processing the message queue is exiting.
11 */
12public final boolean post(Runnable r)
13{
14   return  sendMessageDelayed(getPostMessage(r), 0);
15}
16 
17private static Message getPostMessage(Runnable r) {
18    Message m = Message.obtain();
19    m.callback = r;
20    return m;
21}

Post的message,其callback将是传入的Runnable对象,其他就与send的message一样了。

消息队列中消息的处理

消息队列中的消息是在Looper.loop()中被处理的:

01/**
02 * Run the message queue in this thread. Be sure to call
03 * {@link #quit()} to end the loop.
04 */
05public static void loop() {
06    final Looper me = myLooper();
07    if (me == null) {
08        throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
09    }
10    final MessageQueue queue = me.mQueue;
11 
12    // Make sure the identity of this thread is that of the local process,
13    // and keep track of what that identity token actually is.
14    Binder.clearCallingIdentity();
15    final long ident = Binder.clearCallingIdentity();
16 
17    for (;;) {
18        Message msg = queue.next(); // might block
19        if (msg == null) {
20            // No message indicates that the message queue is quitting.
21            return;
22        }
23 
24        // This must be in a local variable, in case a UI event sets the logger
25        Printer logging = me.mLogging;
26        if (logging != null) {
27            logging.println(">>>>> Dispatching to " + msg.target + " " +
28                    msg.callback + ": " + msg.what);
29        }
30 
31        msg.target.dispatchMessage(msg);
32 
33        if (logging != null) {
34            logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
35        }
36 
37        // Make sure that during the course of dispatching the
38        // identity of the thread wasn't corrupted.
39        final long newIdent = Binder.clearCallingIdentity();
40        if (ident != newIdent) {
41            Log.wtf(TAG, "Thread identity changed from 0x"
42                    + Long.toHexString(ident) + " to 0x"
43                    + Long.toHexString(newIdent) + " while dispatching to "
44                    + msg.target.getClass().getName() + " "
45                    + msg.callback + " what=" + msg.what);
46       }
47 
48        msg.recycle();
49    }
50}

这个函数会调用Handler的dispatchMessage()方法来处理消息,其实也就是msg.target对象的dispatchMessage()方法。此外我们可以看到,在Looper.loop()方法的末尾recycle了从MessageQueue中取出的已经dispatch的消息。从而,我们需要通过Handler向一个Looper线程的MessageQueue中发送消息时,我们只要obtain一个Message然后发送就好了,而不需要自己手动去recycle,这些事情将会由Looper来帮助我们完成。接着来看Handler. dispatchMessage()的实现:

01/**
02 * Handle system messages here.
03 */
04public void dispatchMessage(Message msg) {
05    if (msg.callback != null) {
06        handleCallback(msg);
07    } else {
08        if (mCallback != null) {
09            if (mCallback.handleMessage(msg)) {
10                return;
11            }
12        }
13        handleMessage(msg);
14    }
15}

在Message的callback成员为非空时,会执行handleCallback(msg),否则的话会依据Handler的mCallback是否为空来确定是否要执行mCallback.handleMessage(msg),并执行Handler的handleMessage(msg)。Handler的handleMessage()方法通常需要override,来实现消息处理的主要逻辑。而mCallback则使得开发者可以比较容易的添加一种对Message做一些额外检测的机制,以提升消息处理的效率。

接着我们看一下,Handler.handleCallback(msg)的实现:

1private static void handleCallback(Message message) {
2    message.callback.run();
3}

很简单的一个方法。可见post的消息的特殊之处,即,此类消息将完全绕过Handler中用于处理消息的 handleMessage() 方法,而只会执行消息的sender所实现的Runnable。

Sleep-Wakeup机制

还有一个问题,当MessageQueue中没有Messages时,那Looper线程会做什么呢?它会去不停的轮询消息队列中是否有消息吗?计算机科学发展到现在,闭上眼睛我们都能知道,Looper线程将一定不会去轮询的。也确实,android消息队列机制的实现,同样是会在消息队列为空时,让Looper线程去休眠,当消息队列中有了消息之后,再被唤醒。但这样的机制又是如何实现的呢?

Sleep-Wakeup机制所需设施的建立

我们从Sleep-Wakeup机制所需设施的建立开始看起。回忆前面我们看到的Looper的构造函数,它会创建出来一个MessageQueue对象,而Sleep-Wakeup机制所需设施正是在MessageQueue对象的创建过程中创建出来的。我们接着再来看MessageQueue的构造函数:

1MessageQueue(boolean quitAllowed) {
2    mQuitAllowed = quitAllowed;
3    mPtr = nativeInit();
4}

这个方法调用nativeInit()方法来创建出Sleep-Wakeup机制所需设施。我们来看nativeInit()的实现(在frameworks/base/core/jni/android_os_MessageQueue.cpp中)

01NativeMessageQueue::NativeMessageQueue() : mInCallback(false), mExceptionObj(NULL) {
02    mLooper = Looper::getForThread();
03    if (mLooper == NULL) {
04        mLooper = new Looper(false);
05        Looper::setForThread(mLooper);
06    }
07}
08 
09static jint android_os_MessageQueue_nativeInit(JNIEnv* env, jclass clazz) {
10    NativeMessageQueue* nativeMessageQueue = new NativeMessageQueue();
11    if (!nativeMessageQueue) {
12        jniThrowRuntimeException(env, "Unable to allocate native queue");
13        return 0;
14    }
15 
16    nativeMessageQueue->incStrong(env);
17    return reinterpret_cast<jint>(nativeMessageQueue);
18}
19 
20static JNINativeMethod gMessageQueueMethods[] = {
21    /* name, signature, funcPtr */
22    { "nativeInit", "()I", (void*)android_os_MessageQueue_nativeInit },
23    { "nativeDestroy", "(I)V", (void*)android_os_MessageQueue_nativeDestroy },
24    { "nativePollOnce", "(II)V", (void*)android_os_MessageQueue_nativePollOnce },
25    { "nativeWake", "(I)V", (void*)android_os_MessageQueue_nativeWake }
26};

可以看到,nativeInit()所做的事情,就是创建一个NativeMessageQueue对象,在NativeMessageQueue的构造函数中,会来创建一个Looper对象。与Java层的Looper对象类似,native层的这种Looper对象也是保存在线程局部存储变量中的,每个线程一个。接着我们来看Looper类的构造函数和Looper::getForThread()函数,来了解一下,native层的线程局部存储API的用法(Looper类的实现在frameworks/native/libs/utils/Looper.cpp):

01// Hint for number of file descriptors to be associated with the epoll instance.
02static const int EPOLL_SIZE_HINT = 8;
03 
04// Maximum number of file descriptors for which to retrieve poll events each iteration.
05static const int EPOLL_MAX_EVENTS = 16;
06 
07static pthread_once_t gTLSOnce = PTHREAD_ONCE_INIT;
08static pthread_key_t gTLSKey = 0;
09 
10Looper::Looper(bool allowNonCallbacks) :
11        mAllowNonCallbacks(allowNonCallbacks), mSendingMessage(false),
12        mResponseIndex(0), mNextMessageUptime(LLONG_MAX) {
13    int wakeFds[2];
14    int result = pipe(wakeFds);
15    LOG_ALWAYS_FATAL_IF(result != 0, "Could not create wake pipe.  errno=%d", errno);
16 
17    mWakeReadPipeFd = wakeFds[0];
18    mWakeWritePipeFd = wakeFds[1];
19 
20    result = fcntl(mWakeReadPipeFd, F_SETFL, O_NONBLOCK);
21    LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake read pipe non-blocking.  errno=%d",
22            errno);
23 
24    result = fcntl(mWakeWritePipeFd, F_SETFL, O_NONBLOCK);
25    LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake write pipe non-blocking.  errno=%d",
26            errno);
27 
28    // Allocate the epoll instance and register the wake pipe.
29    mEpollFd = epoll_create(EPOLL_SIZE_HINT);
30    LOG_ALWAYS_FATAL_IF(mEpollFd < 0, "Could not create epoll instance.  errno=%d", errno);
31 
32    struct epoll_event eventItem;
33    memset(& eventItem, 0, sizeof(epoll_event)); // zero out unused members of data field union
34    eventItem.events = EPOLLIN;
35    eventItem.data.fd = mWakeReadPipeFd;
36    result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeReadPipeFd, & eventItem);
37    LOG_ALWAYS_FATAL_IF(result != 0, "Could not add wake read pipe to epoll instance.  errno=%d",
38            errno);
39}
40 
41void Looper::initTLSKey() {
42    int result = pthread_key_create(& gTLSKey, threadDestructor);
43    LOG_ALWAYS_FATAL_IF(result != 0, "Could not allocate TLS key.");
44}
45 
46void Looper::threadDestructor(void *st) {
47    Looper* const self = static_cast<Looper*>(st);
48    if (self != NULL) {
49        self->decStrong((void*)threadDestructor);
50    }
51}
52 
53void Looper::setForThread(const sp<Looper>& looper) {
54    sp<Looper> old = getForThread(); // also has side-effect of initializing TLS
55 
56    if (looper != NULL) {
57        looper->incStrong((void*)threadDestructor);
58    }
59 
60    pthread_setspecific(gTLSKey, looper.get());
61 
62    if (old != NULL) {
63        old->decStrong((void*)threadDestructor);
64    }
65}
66 
67sp<Looper> Looper::getForThread() {
68    int result = pthread_once(& gTLSOnce, initTLSKey);
69    LOG_ALWAYS_FATAL_IF(result != 0, "pthread_once failed");
70 
71    return (Looper*)pthread_getspecific(gTLSKey);
72}

关于pthread库提供的线程局部存储API的用法,可以看到,每个线程局部存储对象,都需要一个key,通过pthread_key_create()函数创建,随后各个线程就可以通过这个key并借助于pthread_setspecific()和pthread_getspecific()函数来保存或者获取相应的线程局部存储的变量了。再来看Looper的构造函数。它创建了一个pipe,两个文件描述符。然后设置管道的两个文件描述属性为非阻塞I/O。接着是创建并设置epoll实例。由此我们了解到,android的消息队列是通过epoll机制来实现Sleep-Wakeup机制的。

唤醒

然后来看当其他线程向Looper线程的MessageQueue中插入了消息时,Looper线程是如何被叫醒的。回忆我们前面看到的MessageQueue类的enqueueMessage()方法,它在最后插入消息之后,有调用一个nativeWake()方法。没错,正是这个nativeWake()方法执行了叫醒Looper线程的动作。那它又是如何叫醒Looper线程的呢?来看它的实现:

01static void android_os_MessageQueue_nativeWake(JNIEnv* env, jclass clazz, jint ptr) {
02    NativeMessageQueue* nativeMessageQueue = reinterpret_cast<NativeMessageQueue*>(ptr);
03    return nativeMessageQueue->wake();
04}
05 
06// ----------------------------------------------------------------------------
07 
08static JNINativeMethod gMessageQueueMethods[] = {
09    /* name, signature, funcPtr */
10    { "nativeInit", "()I", (void*)android_os_MessageQueue_nativeInit },
11    { "nativeDestroy", "(I)V", (void*)android_os_MessageQueue_nativeDestroy },
12    { "nativePollOnce", "(II)V", (void*)android_os_MessageQueue_nativePollOnce },
13    { "nativeWake", "(I)V", (void*)android_os_MessageQueue_nativeWake }
14};

它只是调用了native层的Looper对象的wake()函数。接着再来看native Looper的wake()函数:

01void Looper::wake() {
02#if DEBUG_POLL_AND_WAKE
03    ALOGD("%p ~ wake", this);
04#endif
05 
06    ssize_t nWrite;
07    do {
08        nWrite = write(mWakeWritePipeFd, "W", 1);
09    } while (nWrite == -1 && errno == EINTR);
10 
11    if (nWrite != 1) {
12        if (errno != EAGAIN) {
13            ALOGW("Could not write wake signal, errno=%d", errno);
14        }
15    }
16}

它所做的事情,就是向管道的用于写的那个文件中写入一个“W”字符而已。

休眠

接着是Looper线程休眠的过程。我们知道,Looper线程在Looper.loop()方法中,将会不断地从MessageQueue中取出消息,并处理。不难想象,休眠的时机应该是在取出消息的时候。由Looper.loop()方法的code,我们知道,它是通过MessageQueue.next()方法来从消息队列中取出消息的。我们来看MessageQueue.next()方法的实现:

01Message next() {
02    int pendingIdleHandlerCount = -1; // -1 only during first iteration
03    int nextPollTimeoutMillis = 0;
04 
05    for (;;) {
06        if (nextPollTimeoutMillis != 0) {
07            Binder.flushPendingCommands();
08        }
09        nativePollOnce(mPtr, nextPollTimeoutMillis);
10 
11        synchronized (this) {
12            // Try to retrieve the next message.  Return if found.
13            final long now = SystemClock.uptimeMillis();
14            Message prevMsg = null;
15            Message msg = mMessages;
16            if (msg != null && msg.target == null) {
17                // Stalled by a barrier.  Find the next asynchronous message in the queue.
18                do {
19                    prevMsg = msg;
20                    msg = msg.next;
21                } while (msg != null && !msg.isAsynchronous());
22            }
23            if (msg != null) {
24                if (now < msg.when) {
25                    // Next message is not ready.  Set a timeout to wake up when it is ready.
26                    nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
27                } else {
28                    // Got a message.
29                    mBlocked = false;
30                    if (prevMsg != null) {
31                        prevMsg.next = msg.next;
32                    } else {
33                        mMessages = msg.next;
34                    }
35                    msg.next = null;
36                    if (false) Log.v("MessageQueue", "Returning message: " + msg);
37                    msg.markInUse();
38                    return msg;
39                }
40            } else {
41                // No more messages.
42                nextPollTimeoutMillis = -1;
43            }
44 
45            // Process the quit message now that all pending messages have been handled.
46            if (mQuiting) {
47                dispose();
48                return null;
49            }
50 
51            // If first time idle, then get the number of idlers to run.
52            // Idle handles only run if the queue is empty or if the first message
53            // in the queue (possibly a barrier) is due to be handled in the future.
54            if (pendingIdleHandlerCount < 0
55                    && (mMessages == null || now < mMessages.when)) {
56                pendingIdleHandlerCount = mIdleHandlers.size();
57            }
58            if (pendingIdleHandlerCount <= 0) {
59                // No idle handlers to run.  Loop and wait some more.
60                mBlocked = true;
61                continue;
62            }
63 
64            if (mPendingIdleHandlers == null) {
65                mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];
66            }
67            mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);
68        }
69 
70        // Run the idle handlers.
71        // We only ever reach this code block during the first iteration.
72        for (int i = 0; i < pendingIdleHandlerCount; i++) {
73            final IdleHandler idler = mPendingIdleHandlers[i];
74            mPendingIdleHandlers[i] = null; // release the reference to the handler
75 
76            boolean keep = false;
77            try {
78                keep = idler.queueIdle();
79            } catch (Throwable t) {
80                Log.wtf("MessageQueue", "IdleHandler threw exception", t);
81            }
82 
83            if (!keep) {
84                synchronized (this) {
85                    mIdleHandlers.remove(idler);
86                }
87            }
88        }
89 
90        // Reset the idle handler count to 0 so we do not run them again.
91        pendingIdleHandlerCount = 0;
92 
93        // While calling an idle handler, a new message could have been delivered
94        // so go back and look again for a pending message without waiting.
95        nextPollTimeoutMillis = 0;
96    }
97}

值得注意的是上面那个对于nativePollOnce()的调用。wait机制的实现正在于此。来看这个方法的实现,在native的JNI code里面:

01class MessageQueue : public RefBase {
02public:
03    /* Gets the message queue's looper. */
04    inline sp<Looper> getLooper() const {
05        return mLooper;
06    }
07 
08    /* Checks whether the JNI environment has a pending exception.
09     *
10     * If an exception occurred, logs it together with the specified message,
11     * and calls raiseException() to ensure the exception will be raised when
12     * the callback returns, clears the pending exception from the environment,
13     * then returns true.
14     *
15     * If no exception occurred, returns false.
16     */
17    bool raiseAndClearException(JNIEnv* env, const char* msg);
18 
19    /* Raises an exception from within a callback function.
20     * The exception will be rethrown when control returns to the message queue which
21     * will typically cause the application to crash.
22     *
23     * This message can only be called from within a callback function.  If it is called
24     * at any other time, the process will simply be killed.
25     *
26     * Does nothing if exception is NULL.
27     *
28     * (This method does not take ownership of the exception object reference.
29     * The caller is responsible for releasing its reference when it is done.)
30     */
31    virtual void raiseException(JNIEnv* env, const char* msg, jthrowable exceptionObj) = 0;
32 
33protected:
34    MessageQueue();
35    virtual ~MessageQueue();
36 
37protected:
38    sp<Looper> mLooper;
39};
40 
41class NativeMessageQueue : public MessageQueue {
42public:
43    NativeMessageQueue();
44    virtual ~NativeMessageQueue();
45 
46    virtual void raiseException(JNIEnv* env, const char* msg, jthrowable exceptionObj);
47 
48    void pollOnce(JNIEnv* env, int timeoutMillis);
49 
50    void wake();
51 
52private:
53    bool mInCallback;
54    jthrowable mExceptionObj;
55};
56 
57void NativeMessageQueue::pollOnce(JNIEnv* env, int timeoutMillis) {
58    mInCallback = true;
59    mLooper->pollOnce(timeoutMillis);
60    mInCallback = false;
61    if (mExceptionObj) {
62        env->Throw(mExceptionObj);
63        env->DeleteLocalRef(mExceptionObj);
64        mExceptionObj = NULL;
65    }
66}
67 
68static void android_os_MessageQueue_nativePollOnce(JNIEnv* env, jclass clazz,
69        jint ptr, jint timeoutMillis) {
70    NativeMessageQueue* nativeMessageQueue = reinterpret_cast<NativeMessageQueue*>(ptr);
71    nativeMessageQueue->pollOnce(env, timeoutMillis);
72}

继续追Looper::pollOnce()的实现(在frameworks/native/libs/utils/Looper.cpp):

001int Looper::pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData) {
002    int result = 0;
003    for (;;) {
004        while (mResponseIndex < mResponses.size()) {
005            const Response& response = mResponses.itemAt(mResponseIndex++);
006            int ident = response.request.ident;
007            if (ident >= 0) {
008                int fd = response.request.fd;
009                int events = response.events;
010                void* data = response.request.data;
011#if DEBUG_POLL_AND_WAKE
012                ALOGD("%p ~ pollOnce - returning signalled identifier %d: "
013                        "fd=%d, events=0x%x, data=%p",
014                        this, ident, fd, events, data);
015#endif
016                if (outFd != NULL) *outFd = fd;
017                if (outEvents != NULL) *outEvents = events;
018                if (outData != NULL) *outData = data;
019                return ident;
020            }
021        }
022 
023        if (result != 0) {
024#if DEBUG_POLL_AND_WAKE
025            ALOGD("%p ~ pollOnce - returning result %d", this, result);
026#endif
027            if (outFd != NULL) *outFd = 0;
028            if (outEvents != NULL) *outEvents = 0;
029            if (outData != NULL) *outData = NULL;
030            return result;
031        }
032 
033        result = pollInner(timeoutMillis);
034    }
035}
036 
037int Looper::pollInner(int timeoutMillis) {
038#if DEBUG_POLL_AND_WAKE
039    ALOGD("%p ~ pollOnce - waiting: timeoutMillis=%d", this, timeoutMillis);
040#endif
041 
042    // Adjust the timeout based on when the next message is due.
043    if (timeoutMillis != 0 && mNextMessageUptime != LLONG_MAX) {
044        nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
045        int messageTimeoutMillis = toMillisecondTimeoutDelay(now, mNextMessageUptime);
046        if (messageTimeoutMillis >= 0
047                && (timeoutMillis < 0 || messageTimeoutMillis < timeoutMillis)) {
048            timeoutMillis = messageTimeoutMillis;
049        }
050#if DEBUG_POLL_AND_WAKE
051        ALOGD("%p ~ pollOnce - next message in %lldns, adjusted timeout: timeoutMillis=%d",
052                this, mNextMessageUptime - now, timeoutMillis);
053#endif
054    }
055 
056    // Poll.
057    int result = ALOOPER_POLL_WAKE;
058    mResponses.clear();
059    mResponseIndex = 0;
060 
061    struct epoll_event eventItems[EPOLL_MAX_EVENTS];
062    int eventCount = epoll_wait(mEpollFd, eventItems, EPOLL_MAX_EVENTS, timeoutMillis);
063 
064    // Acquire lock.
065    mLock.lock();
066 
067    // Check for poll error.
068    if (eventCount < 0) {
069        if (errno == EINTR) {
070            goto Done;
071        }
072        ALOGW("Poll failed with an unexpected error, errno=%d", errno);
073        result = ALOOPER_POLL_ERROR;
074        goto Done;
075    }
076 
077    // Check for poll timeout.
078    if (eventCount == 0) {
079#if DEBUG_POLL_AND_WAKE
080        ALOGD("%p ~ pollOnce - timeout", this);
081#endif
082        result = ALOOPER_POLL_TIMEOUT;
083        goto Done;
084    }
085 
086    // Handle all events.
087#if DEBUG_POLL_AND_WAKE
088    ALOGD("%p ~ pollOnce - handling events from %d fds", this, eventCount);
089#endif
090 
091    for (int i = 0; i < eventCount; i++) {
092        int fd = eventItems[i].data.fd;
093        uint32_t epollEvents = eventItems[i].events;
094        if (fd == mWakeReadPipeFd) {
095            if (epollEvents & EPOLLIN) {
096                awoken();
097            } else {
098                ALOGW("Ignoring unexpected epoll events 0x%x on wake read pipe.", epollEvents);
099            }
100        } else {
101            ssize_t requestIndex = mRequests.indexOfKey(fd);
102            if (requestIndex >= 0) {
103                int events = 0;
104                if (epollEvents & EPOLLIN) events |= ALOOPER_EVENT_INPUT;
105                if (epollEvents & EPOLLOUT) events |= ALOOPER_EVENT_OUTPUT;
106                if (epollEvents & EPOLLERR) events |= ALOOPER_EVENT_ERROR;
107                if (epollEvents & EPOLLHUP) events |= ALOOPER_EVENT_HANGUP;
108                pushResponse(events, mRequests.valueAt(requestIndex));
109            } else {
110                ALOGW("Ignoring unexpected epoll events 0x%x on fd %d that is "
111                        "no longer registered.", epollEvents, fd);
112            }
113        }
114    }
115Done: ;
116 
117    // Invoke pending message callbacks.
118    mNextMessageUptime = LLONG_MAX;
119    while (mMessageEnvelopes.size() != 0) {
120        nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
121        const MessageEnvelope& messageEnvelope = mMessageEnvelopes.itemAt(0);
122        if (messageEnvelope.uptime <= now) {
123            // Remove the envelope from the list.
124            // We keep a strong reference to the handler until the call to handleMessage
125            // finishes.  Then we drop it so that the handler can be deleted *before*
126            // we reacquire our lock.
127            { // obtain handler
128                sp<MessageHandler> handler = messageEnvelope.handler;
129                Message message = messageEnvelope.message;
130                mMessageEnvelopes.removeAt(0);
131                mSendingMessage = true;
132                mLock.unlock();
133 
134#if DEBUG_POLL_AND_WAKE || DEBUG_CALLBACKS
135                ALOGD("%p ~ pollOnce - sending message: handler=%p, what=%d",
136                        this, handler.get(), message.what);
137#endif
138                handler->handleMessage(message);
139            } // release handler
140 
141            mLock.lock();
142            mSendingMessage = false;
143            result = ALOOPER_POLL_CALLBACK;
144        } else {
145            // The last message left at the head of the queue determines the next wakeup time.
146            mNextMessageUptime = messageEnvelope.uptime;
147            break;
148        }
149    }
150 
151    // Release lock.
152    mLock.unlock();
153 
154    // Invoke all response callbacks.
155    for (size_t i = 0; i < mResponses.size(); i++) {
156        Response& response = mResponses.editItemAt(i);
157        if (response.request.ident == ALOOPER_POLL_CALLBACK) {
158            int fd = response.request.fd;
159            int events = response.events;
160            void* data = response.request.data;
161#if DEBUG_POLL_AND_WAKE || DEBUG_CALLBACKS
162            ALOGD("%p ~ pollOnce - invoking fd event callback %p: fd=%d, events=0x%x, data=%p",
163                    this, response.request.callback.get(), fd, events, data);
164#endif
165            int callbackResult = response.request.callback->handleEvent(fd, events, data);
166            if (callbackResult == 0) {
167                removeFd(fd);
168            }
169            // Clear the callback reference in the response structure promptly because we
170            // will not clear the response vector itself until the next poll.
171            response.request.callback.clear();
172            result = ALOOPER_POLL_CALLBACK;
173        }
174    }
175    return result;
176}

它通过调用epoll_wait()函数来等待消息的到来。

Done。

转载自http://my.oschina.net/wolfcs/blog/160601

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值