Android framework层的Handler, Looper和MessageQueue

发布时间:2023年12月27日


在Android中, Thread并不是天然具有消息处理机制的,为了给 Thread赋予消息处理机制,Android为引入了 Looper.
在具有 LooperThread中,这几个类的关系为:

  1. 一个Thread有一个Looper(一对一)
  2. 一个Looper中有一个MessageQueue(一对一)
  3. Looper不停的从MessageQueue中取出消息并通过Handler进行处理

为Thread添加Looper

Looper.java中,有这样一段关于Looper的介绍。只要在Threadrun()中调用Looper.prepare()可以给Thread添加一个Looper对象,调用Looper.loop()可以让刚刚创建的Looper对象进入循环,不断取出消息并通过Handler进行处理。

frameworks/base/core/java/android/os/Looper.java

/**
  * 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
  * {@link #prepare} in the thread that is to run the loop, and then
  * {@link #loop} to have it process messages until the loop is stopped.
  *
  * <p>Most interaction with a message loop is through the
  * {@link Handler} class.
  *
  * <p>This is a typical example of the implementation of a Looper thread,
  * using the separation of {@link #prepare} and {@link #loop} to create an
  * initial Handler to communicate with the Looper.
  *
  * <pre>
  *  class LooperThread extends Thread {
  *      public Handler mHandler;
  *
  *      public void run() {
  *          Looper.prepare();
  *
  *          mHandler = new Handler(Looper.myLooper()) {
  *              public void handleMessage(Message msg) {
  *                  // process incoming messages here
  *              }
  *          };
  *
  *          Looper.loop();
  *      }
  *  }</pre>
  */

Looper.prepare()实现

实际上Looper.prepare()做的事情非常简单,它就是新建了一个Looper对象并"赋值"给了线程私有变量,sThreadLocal

frameworks/base/core/java/android/os/Looper.java

    /** 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));
    }

sThreadLocal的实现非常简单,可以理解为它内置了一个MapkeyThread对象,value则是线程私有的变量。所以对他进行"赋值"时,要使用set方法而不是"="。

Looper中的MessageQueueLooper.loop()

Looper中有一个MessageQueue对象mQueue.

frameworks/base/core/java/android/os/Looper.java

    @UnsupportedAppUsage
    final MessageQueue mQueue;
frameworks/base/core/java/android/os/Looper.java

    /**
     * Run the message queue in this thread. Be sure to call
     * {@link #quit()} to end the loop.
     */
    @SuppressWarnings({"UnusedTokenOfOriginalCallingIdentity",
            "ClearIdentityCallNotFollowedByTryFinally",
            "ResultOfClearIdentityCallNotStoredInVariable"})
    public static void loop() {
        final Looper me = myLooper();
        if (me == null) {
            throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
        }
        if (me.mInLoop) {
            Slog.w(TAG, "Loop again would have the queued messages be executed"
                    + " before this one completed.");
        }

        me.mInLoop = true; //标记当前线程已在loop循环当中

        // 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();
        final long ident = Binder.clearCallingIdentity();

        // Allow overriding a threshold with a system prop. e.g.
        // adb shell 'setprop log.looper.1000.main.slow 1 && stop && start'
        final int thresholdOverride =
                SystemProperties.getInt("log.looper."
                        + Process.myUid() + "."
                        + Thread.currentThread().getName()
                        + ".slow", -1);

        me.mSlowDeliveryDetected = false;

        for (;;) {
            //不断调用loopOnce处理消息
            if (!loopOnce(me, ident, thresholdOverride)) {
                return;
            }
        }
    }
frameworks/base/core/java/android/os/Looper.java

    /**
     * Poll and deliver single message, return true if the outer loop should continue.
     */
    @SuppressWarnings({"UnusedTokenOfOriginalCallingIdentity",
            "ClearIdentityCallNotFollowedByTryFinally"})
    private static boolean loopOnce(final Looper me,
            final long ident, final int thresholdOverride) {
        // 从mQueue中取出下一个消息,线程有可能在此阻塞。
        Message msg = me.mQueue.next(); // might block
        if (msg == null) {
            // No message indicates that the message queue is quitting.
            return false;
        }
        ...
        try {
            //调用msg.target.dispatchMessage处理消息。实际上就是通过Handler来处理消息。
            msg.target.dispatchMessage(msg);
            if (observer != null) {
                observer.messageDispatched(token, msg);
            }
            dispatchEnd = needEndTime ? SystemClock.uptimeMillis() : 0;
        } catch (Exception exception) {
            if (observer != null) {
                observer.dispatchingThrewException(token, msg, exception);
            }
            throw exception;
        } finally {
            ThreadLocalWorkSource.restore(origWorkSource);
            if (traceTag != 0) {
                Trace.traceEnd(traceTag);
            }
        }
        ...
        return true;
    }

msg.target实际上就是一个Handler对象

frameworks/base/core/java/android/os/Message.java

    @UnsupportedAppUsage
    /*package*/ Handler target;

使用Handler发送和处理消息

Handler构造函数

我们这里只需要关心mLooper, mQueuemCallback
之前说过,Handler只是用来处理消息,从MessageQueue中取出消息并调用Handler进行处理是在Looper中进行的。所以在new一个Handler对象的时候,需要给他指定一个Looper,这个Looper会调用新建的Handler处理消息。通过Handler发送的消息,会添加到mQueue队列中,并通过mLooper不断取出再调用Handler进行处理。

frameworks/base/core/java/android/os/Handler.java

    /** @hide */
    public Handler(@NonNull Looper looper, @Nullable Callback callback, boolean async,
            boolean shared) {
        mLooper = looper;
        mQueue = looper.mQueue;
        mCallback = callback;
        mAsynchronous = async;
        mIsShared = shared;
    }

mCallback则是用来处理消息的关键,我们在日常使用中,一般是通过如下方式处理消息:

  1. 在一个对象中实现Handler.Callback
  2. 将该对象传给HandlermCallback
  3. Handler会调用mCallbackhandleMessage方法处理消息。
frameworks/base/core/java/android/os/Handler.java

    /**
     * Callback interface you can use when instantiating a Handler to avoid
     * having to implement your own subclass of Handler.
     */
    public interface Callback {
        /**
         * @param msg A {@link android.os.Message Message} object
         * @return True if no further handling is desired
         */
        boolean handleMessage(@NonNull Message msg);
    }

Handler发送消息

通过Handler发送消息最终会调用到sendMessageAtTime,它会调用enqueueMessage将消息加入mQueue(也就是mLoopermQueue)。

frameworks/base/core/java/android/os/Handler.java

public boolean sendMessageAtTime(@NonNull 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);
    }

我们看到,在enqueueMessage中会将msg.target设置为当前的Handler。前面说过,Looper会调用 msg.target.dispatchMessage处理消息,这也就保证了,发送和处理消息的Handler是同一个。

frameworks/base/core/java/android/os/Handler.java

    private boolean enqueueMessage(@NonNull MessageQueue queue, @NonNull Message msg,
            long uptimeMillis) {
        msg.target = this;//将msg.target设置为当前的Handler对象
        msg.workSourceUid = ThreadLocalWorkSource.getUid();

        if (mAsynchronous) {
            msg.setAsynchronous(true);
        }
        return queue.enqueueMessage(msg, uptimeMillis);
    }

Handler处理消息

dispatchMessage处理消息的流程中,有三种处理方式

  1. 如果message中携带了Runnable对象,那么就调用他的run()方法
  2. 如果没有Runnable对象,并且mCallback不为空,那么调用mCallback进行处理
  3. 否则调用Handler自身的HandleMessage进行处理。
frameworks/base/core/java/android/os/Handler.java

    public void dispatchMessage(@NonNull 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();
    }

HandlerhandleMessage本身是没有处理逻辑的,如果想要使用Handler.handleMessage进行处理,则需要新建Handler的子类并重写handleMessage方法。

frameworks/base/core/java/android/os/Handler.java

    /**
     * Subclasses must implement this to receive messages.
     */
    public void handleMessage(@NonNull Message msg) {
    }
文章来源:https://blog.csdn.net/weixin_42352096/article/details/135232322
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。