码迷,mamicode.com
首页 > 其他好文 > 详细

Looper: Looper,Handler,MessageQueue三者之间的联系

时间:2019-09-20 18:30:55      阅读:88      评论:0      收藏:0      [点我收藏+]

标签:boolean   推荐   after   bar   var   tin   aced   rgs   androi   

在Android中每个应用的UI线程是被保护的,不能在UI线程中进行耗时的操作,其他的子线程也不能直接进行UI操作。为了达到这个目的Android设计了handler Looper这个系统框架,Android 推荐把耗时的操作放到子线程中去执行,子线程执行完毕后如果想通知UI更新,可以通过给主线程的Handler发送Message的方式来予以实现,说起Handler就不得不提到它的另外两个伙伴:Looper和MessageQueue,它们三者之间的关系如下:

 

Handler: 消息处理者(发送消息和处理消息)。
MessageQueue: 消息队列(承载消息的容器)。
Looper: 管理者(管理消息队列,不断的从MessageQueue中读取消息交给Handler进行处理)。

 

以子线程向主线程发送一条消息为例,当在一条子线程中调用mHandler.sendMessage(msg)时,它的执行过程如下:

1. Handler会依次调用 sendMessageDelayed() 、 sendMessageAtTime() 、 enqueueMessage() 方法将消息压入MessageQueue。

1.1 sendMessage

    /**
     * Pushes a message onto the end of the message queue after all pending messages
     * before the current time. It will be received in {@link #handleMessage},
     * in the thread attached to this handler.
     *  
     * @return Returns true if the message was successfully placed in to the 
     *         message queue.  Returns false on failure, usually because the
     *         looper processing the message queue is exiting.
     */
    public final boolean sendMessage(Message msg)
    {
        return sendMessageDelayed(msg, 0);
    }

1.2 sendMessageDelayed

    /**
     * Enqueue a message into the message queue after all pending messages
     * before (current time + delayMillis). You will receive it in
     * {@link #handleMessage}, in the thread attached to this handler.
     *  
     * @return Returns true if the message was successfully placed in to the 
     *         message queue.  Returns false on failure, usually because the
     *         looper processing the message queue is exiting.  Note that a
     *         result of true does not mean the message will be processed -- if
     *         the looper is quit before the delivery time of the message
     *         occurs then the message will be dropped.
     */
    public final boolean sendMessageDelayed(Message msg, long delayMillis)
    {
        if (delayMillis < 0) {
            delayMillis = 0;
        }
        return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
    }

1.3 sendMessageAtTime

    /**
     * Enqueue a message into the message queue after all pending messages
     * before the absolute time (in milliseconds) <var>uptimeMillis</var>.
     * <b>The time-base is {@link android.os.SystemClock#uptimeMillis}.</b>
     * Time spent in deep sleep will add an additional delay to execution.
     * You will receive it in {@link #handleMessage}, in the thread attached
     * to this handler.
     * 
     * @param uptimeMillis The absolute time at which the message should be
     *         delivered, using the
     *         {@link android.os.SystemClock#uptimeMillis} time-base.
     *         
     * @return Returns true if the message was successfully placed in to the 
     *         message queue.  Returns false on failure, usually because the
     *         looper processing the message queue is exiting.  Note that a
     *         result of true does not mean the message will be processed -- if
     *         the looper is quit before the delivery time of the message
     *         occurs then the message will be dropped.
     */
    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);
    }

这里的mQueue其实是Handler已经持有的一个成员变量,在Handler的构造方法中通过Looper对象身上获取到的,Looper对象本身就含有一个MessageQueue。

    /**
     * Use the provided {@link Looper} instead of the default one and take a callback
     * interface in which to handle messages.  Also set whether the handler
     * should be asynchronous.
     *
     * Handlers are synchronous by default unless this constructor is used to make
     * one that is strictly asynchronous.
     *
     * Asynchronous messages represent interrupts or events that do not require global ordering
     * with respect to synchronous messages.  Asynchronous messages are not subject to
     * the synchronization barriers introduced by {@link MessageQueue#enqueueSyncBarrier(long)}.
     *
     * @param looper The looper, must not be null.
     * @param callback The callback interface in which to handle messages, or null.
     * @param async If true, the handler calls {@link Message#setAsynchronous(boolean)} for
     * each {@link Message} that is sent to it or {@link Runnable} that is posted to it.
     *
     * @hide
     */
    public Handler(Looper looper, Callback callback, boolean async) {
        mLooper = looper;
        mQueue = looper.mQueue;
        mCallback = callback;
        mAsynchronous = async;
    }

1.4 enqueueMessage

    private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
        msg.target = this;
        if (mAsynchronous) {
            msg.setAsynchronous(true);
        }
        return queue.enqueueMessage(msg, uptimeMillis);
    }

在enqueueMessage方法中通过调用MessageQueue的enqueueMessage()方法将消息压入消息队列。

2. 以上是入队的操作,接下来主线程通过Looper.loop()方法不断的从消息队列中获取消息,并交给其指定的Handler进行处理:

这里有个问题,主线程的Looper是什么时候启动的?我们知道,Google设计Looper的目的就是为了在一个线程里运行一个消息循环,但是Looper需要调用 prepare() 方法才能运行起来,调用 loop() 方法开始处理消息。那么这两个方法在哪里开始调用的?

一般说来,Android程序的入口点可以认为是android.app.ActivityThread类的main()方法(Android 2.3):

public static final void main(String[] args) {
        SamplingProfilerIntegration.start();

        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();

        if (Process.supportsProcesses()) {
            throw new RuntimeException("Main thread loop unexpectedly exited");
        }

        thread.detach();
        String name = (thread.mInitialApplication != null)
            ? thread.mInitialApplication.getPackageName()
            : "<unknown>";
        Slog.i(TAG, "Main thread of " + name + " is now exiting");
    }

果然,在这个方法里找到了prepare()和loop()方法的调用,这说明程序在启动的时候就自动开始了Looper的运转。接下来就要看出队的操作了,Looper通过调用loop()方法开始处理消息,来到Looper.java:

2.1 loop()

public static final void loop() {
    Looper me = myLooper();
    MessageQueue queue = me.mQueue;
    while (true) {
        Message msg = queue.next(); // might block
        if (msg != null) {
            if (msg.target == null) {
                return;
            }
            if (me.mLogging!= null) me.mLogging.println(
                    ">>>>> Dispatching to " + msg.target + " "
                    + msg.callback + ": " + msg.what
                    );
            msg.target.dispatchMessage(msg);
            if (me.mLogging!= null) me.mLogging.println(
                    "<<<<< Finished to    " + msg.target + " "
                    + msg.callback);
            msg.recycle();
        }
    }
}

可以看到,它内部起了一个死循环,并不断的从队列中获取Message, 然后通过调用  msg.target.dispatchMessage(msg); 方法将消息分发出去, 这里的target就是之前指定处理该消息的Handler, 从这里也可以看出,一个界面可以有很多个Handler,因为最终消息都会被分发到它所指定的那个Handler上面去。

2.2 dispatchMessage

public void dispatchMessage(Message msg) {
    if (msg.callback != null) {
        handleCallback(msg);
    } else {
        if (mCallback != null) {
            if (mCallback.handleMessage(msg)) {
                return;
            }
        }
        handleMessage(msg);
    }
}

这里首先对Message的callback做了判断,如果它自身的callback不为空,就调用handleCallback处理该消息,那什么时候Message的callback不为空呢?其实是在调用Handler的post(Runnable r)方法发送消息的时候:

技术图片
    /**
     * Causes the Runnable r to be added to the message queue.
     * The runnable will be run on the thread to which this handler is 
     * attached. 
     *  
     * @param r The Runnable that will be executed.
     * 
     * @return Returns true if the Runnable was successfully placed in to the 
     *         message queue.  Returns false on failure, usually because the
     *         looper processing the message queue is exiting.
     */
    public final boolean post(Runnable r)
    {
       return  sendMessageDelayed(getPostMessage(r), 0);
    }
Handler#post(Runnable r)
技术图片
    private static Message getPostMessage(Runnable r) {
        Message m = Message.obtain();
        m.callback = r;
        return m;
    }
getPostMessage

那这个mCallback是个什么东西呢,它其实是Handler的构造方法中传入的用于处理具体msg的一个类:

    /**
     * Use the provided {@link Looper} instead of the default one and take a callback
     * interface in which to handle messages.  Also set whether the handler
     * should be asynchronous.
     *
     * Handlers are synchronous by default unless this constructor is used to make
     * one that is strictly asynchronous.
     *
     * Asynchronous messages represent interrupts or events that do not require global ordering
     * with respect to synchronous messages.  Asynchronous messages are not subject to
     * the synchronization barriers introduced by {@link MessageQueue#enqueueSyncBarrier(long)}.
     *
     * @param looper The looper, must not be null.
     * @param callback The callback interface in which to handle messages, or null.
     * @param async If true, the handler calls {@link Message#setAsynchronous(boolean)} for
     * each {@link Message} that is sent to it or {@link Runnable} that is posted to it.
     *
     * @hide
     */
    public Handler(Looper looper, Callback callback, boolean async) {
        mLooper = looper;
        mQueue = looper.mQueue;
        mCallback = callback;
        mAsynchronous = async;
    }

接下来就很简单了,如果mCallback不为null,就调用了mCallback的handleMessage来处理消息,如果mCallback为null,就直接调用Handler的handleMessage来处理消息,注意到,Handle本身的handleMessage()方法其实是个空方法:

    /**
     * Subclasses must implement this to receive messages.
     */
    public void handleMessage(Message msg) {
    }

我们一般在使用Handler在处理Message的时候都会将其重写。

同时,这里面还有一个很有意思的现象:如果我们是把Handler作为成员变量在Activity中实例化的,那么handleMessage()方法中的代码就是在主线程执行,如果Handler是在子线程中实例化的,那么handleMessage()中的代码就是在子线程中去执行,这样主线程还能利用该Handler与子线程进行通信。

总结:整个执行流程就是:

1.Handler先将指定的Message压入到Looper对象的MessageQueue中;

2.Looper对象会调用loop()方法不断的从MessageQueue中获取消息;

3.当拿到一条消息后,会根据该Message的target选择合适的Handler并调用其handleMessage()方法对消息进行处理。

参考链接:

1. 郭神-Android异步消息处理机制完全解析,带你从源码的角度彻底理解

2.Android源代码在线

3.Android中为什么主线程不会因为Looper.loop()方法造成阻塞

 

Looper: Looper,Handler,MessageQueue三者之间的联系

标签:boolean   推荐   after   bar   var   tin   aced   rgs   androi   

原文地址:https://www.cnblogs.com/yongdaimi/p/11558815.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!