10分钟 吃透Handler完整原理机制

2022-02-26  本文已影响0人  jalen2024

Handler 原理 大白话

4个角色

主要从源码部分了解以下几个核心重要的方法

1.1Looper.prepare()

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

校验当前线程是否存在looper对象,如果不存在则创建 (ThreadLocal维护着looper)。

  private Looper(boolean quitAllowed) {
        mQueue = new MessageQueue(quitAllowed);
        mThread = Thread.currentThread();
    }

构造方法创建的时候会生成1个messageQueue队列,同时将当前线程和looper绑定

1.2looper.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;
            }

            // This must be in a local variable, in case a UI event sets the logger
            final Printer logging = me.mLogging;
            if (logging != null) {
                logging.println(">>>>> Dispatching to " + msg.target + " " +
                        msg.callback + ": " + msg.what);
            }
            ........

死循环查询messageQueue中是否有消息,如果没有的话就休眠 等待唤醒

try {
                msg.target.dispatchMessage(msg);
                dispatchEnd = needEndTime ? SystemClock.uptimeMillis() : 0;
            } finally {
                if (traceTag != 0) {
                    Trace.traceEnd(traceTag);
                }
            }

1.2创建handler Handler()

  public Handler(Callback callback, boolean async) {
        if (FIND_POTENTIAL_LEAKS) {
            final Class<? extends Handler> klass = getClass();
            if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
                    (klass.getModifiers() & Modifier.STATIC) == 0) {
                Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
                    klass.getCanonicalName());
            }
        }

        mLooper = Looper.myLooper();
        if (mLooper == null) {
            throw new RuntimeException(
                "Can't create handler inside thread " + Thread.currentThread()
                        + " that has not called Looper.prepare()");
        }
        mQueue = mLooper.mQueue;
        mCallback = callback;
        mAsynchronous = async;
    }

在当前线程创建Handler,同时获取当前线程的looper,获取当前线程looper里的消息队列

1.4 handler发送消息 Handler.sendMessage

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

将msg和handler绑定,

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

同时将message推到looper中的messageQueue消息队列中,如下1.5里的处理。

1.5处理消息 MessageQueue

主要用来存取消息队列的

boolean enqueueMessage(Message msg, long when) {
        if (msg.target == null) {
            throw new IllegalArgumentException("Message must have a target.");
        }

2引发提问

2.1 1个looper可以和几个线程绑定,一个messageQueue又能和几个looper绑定

答案:1个线程和1个looper绑定,1个looper里面只有一个messageQueue.

同时1个线程里是可以有多个handler,哪个handler发的消息就由哪个handler进行处理消息。

2.2 handler怎么去延时发送消息 原理是什么样的

在looper的loop循环方法中会不断去调用messageQueue里的next方法[如上1.2中代码],这个方法里面会根据消息的实际执行时间进行插入,

底层都是调用的sendMessageDelayed, 普通消息是延迟0秒, 延迟消息是延迟N毫秒。

2.3 handlerMessage和dispatchMessage的区别

dispatchMessage的底层最终还是调用的handlerMessage,但除此之外它还对msg和handler里带callback单独处理。

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

猜你喜欢

热点阅读