在任意线程给Handler发送的消息为什么会在创建Handler的那个线程被执行?

来源:互联网 发布:网络大电影产值 编辑:程序博客网 时间:2024/06/02 13:41

    接触Android一定对Handler不陌生,它是用来处理线程间通信问题。例如如下代码:

public class HandlerTestActivity extends Activity {Handler mHandler = new Handler() {    @Override    public void handleMessage(Message msg) {    // 在主线程处理这个消息    }};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);new Thread(new Runnable() {@Overridepublic void run() {mHandler.sendEmptyMessage(1);}}).start();}}

    那么问题来了,明明是在子线程中发出的消息给Handler,但是为什么最终会在主线程中处理呢?下面来分析下。


    分析之前,必须要知道Handler与Looper、MessageQueue和Message的关系,请度娘看看相关资料。

    了解以上的关系之后,我们就可以开始探讨上面那个问题:

    1、如果我们需要在子线程创建一个Handler时,我们需要这么做:

    

Looper.prepare();Handler handler = new Handler();Looper.loop();
   这是首先为当前线程创建一个消息循环Looper给Handler使用,Looper.loop()进行循环获取消息。


  延伸:为什么在主线程创建Handler不需要调用Looper.prepare()和Looper.loop()呢?

            这是因为系统在启动程序的时候,已经在ActivityThread进行了上面的操作,这是源码:

           

public static void main(String[] args) {        SamplingProfilerIntegration.start();        // CloseGuard defaults to true and can be quite spammy.  We        // disable it here, but selectively enable it later (via        // StrictMode) on debug builds, but using DropBox, not logs.        CloseGuard.setEnabled(false);        Process.setArgV0("<pre-initialized>");        Looper.prepareMainLooper();        if (sMainThreadHandler == null) {            sMainThreadHandler = new Handler();        }        ActivityThread thread = new ActivityThread();        thread.attach(false);        if (false) {            Looper.myLooper().setMessageLogging(new                    LogPrinter(Log.DEBUG, "ActivityThread"));        }        Looper.loop();        throw new RuntimeException("Main thread loop unexpectedly exited");    }


    2、我们使用Handler发送消息时,无论在哪个线程发送,最终会把消息保存在消息队列里,也就是保存到MessageQueue里,请看源码:

        

public class Handler {/**     * 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);        }    }        public final boolean sendMessage(Message msg)    {        return sendMessageDelayed(msg, 0);    }    public final boolean sendEmptyMessage(int what)    {        return sendEmptyMessageDelayed(what, 0);    }    public final boolean sendEmptyMessageDelayed(int what, long delayMillis) {        Message msg = Message.obtain();        msg.what = what;        return sendMessageDelayed(msg, delayMillis);    }    public final boolean sendEmptyMessageAtTime(int what, long uptimeMillis) {        Message msg = Message.obtain();        msg.what = what;        return sendMessageAtTime(msg, uptimeMillis);    }    public final boolean sendMessageDelayed(Message msg, long delayMillis)    {        if (delayMillis < 0) {            delayMillis = 0;        }        return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);    }            public boolean sendMessageAtTime(Message msg, long uptimeMillis) {                // 所有消息发送最终都会调用这个方法                MessageQueue queue = mQueue;        if (queue == null) {            RuntimeException e = new RuntimeException(                    this + " sendMessageAtTime() called with no mQueue");            Log.w("Looper", e.getMessage(), e);            return false;        }        return enqueueMessage(queue, msg, uptimeMillis);// 将消息保存到MessageQueue queue里面    }}

    


    消息保存到MessageQueue之后,谁来取消息把它给Handler处理呢?没错,就是Looper,请看源码:

   

public final class Looper {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.target也就是执行这个消息的Handler            ...        }    }}

   

     所以,整个流程就是这样的:

    1、在任意地方通过Handler给自己发送消息Message,并把Message排好队保存在MessageQueue里;

    2、Handler所处线程的那个Looper进行循环到MessageQueue里取消息,并把消息按时传到Handler执行。

    就这么两步!

    所以究竟消息是在哪个线程被Handler处理呢?答案是Looper进行循环的那个线程,也就是创建Handler那个线程。因为是在Looper.loop调用Handler去执行消息的,Looper在哪个线程调用,消息就在哪个线程被Handler处理:

<pre name="code" class="java">msg.target.dispatchMessage(msg);  // msg.target也就是执行这个消息的Handler

    因为对应Looper所在线程与创建对应Handler的线程必须是同一条,所以无论从哪个线程发送消息给Handler,最终会在创建Handler那个线程执行这个消息。


0 0
原创粉丝点击