Handler消息传递机制解析

2019-12-20  本文已影响0人  钦_79f7

Handler工作过程简述

以主线程为例,从APP创建主线程开始,就为主线程创建了一个不可退出的looper,通过getMainLooper()可以获得其对象,以及有了一个looper相对应的队列mQueue,然后主线程中所有的handler,都是通过此唯一的looper进行分发派送消息,所有的msg,也都是依次排列在此唯一的mQueue中,等待looper进行接收分发。由于mQueue中的msg是依次出队的,所以在Activity onCreate()中执行View的post操作可以相应的达到一定的延迟作用。

Looper

Fields

  1. ThreadLocal<Looper> sThreadLocal:保存当前线程的本地变量,保证一个线程只有looper对象存在;
  2. Looper sMainLooper:UI线程的looper对象;
  3. MessageQueue mQueue:当前looper对应的消息队列;
  4. Thread mThread:记录当前处于的线程对象;

Methods

  1. quit()/quitSafely():用于退出当前looper循环(仅仅在子线程中的looper有效,主线程的looper创建之初就不可以退出循环),其内部是调用的mQueue的quit(boolen)方法,mQueue的mQuitAllowed属性记录着当前looper对象是否允许退出循环操作;

    public void quit() {
        mQueue.quit(false);
    }
     public void quitSafely() {
        mQueue.quit(true);
    }
    
  2. static Looper getMainLooper():获取主线程的looper对象;

  3. public static void prepare():子线程中调用,创建子线程的looper(并且允许退出循环);

  4. public static @Nullable Looper myLooper():获取当前线程的looper;

  5. public static @NonNull MessageQueue myQueue():获取当前线程的消息队列;

  6. public @NonNull Thread getThread():获取looper的线程对象;

  7. public boolean isCurrentThread():判断当前线程与looper对应的线程是否一致;

  8. public static void loop():循环接收消息,通过mQueue.next()来不停获取下一个msg,并根据msg.target进行消息的分发,msg.target是当前handler对象,调用handler.dispatchMessage(msg)将此msg交给handler处理。

MessageQueue

Fields

  1. private final boolean mQuitAllowed:是否允许looper退出循环;

Methods

  1. boolean enqueueMessage(Message msg, long when):将消息压入队列中,判断当前队列中是否有消息,没有则处于队首;或者根据msg.when来确定此msg是否要排在队首,还在插在队列中间某个位置;

    boolean enqueueMessage(Message msg, long when) {
        if (msg.target == null) {
            throw new IllegalArgumentException("Message must have a target.");
        }
        if (msg.isInUse()) {
            throw new IllegalStateException(msg + " This message is already in use.");
        }
    
        synchronized (this) {
            if (mQuitting) {
                IllegalStateException e = new IllegalStateException(
                        msg.target + " sending message to a Handler on a dead thread");
                Log.w(TAG, e.getMessage(), e);
                msg.recycle();
                return false;
            }
    
            msg.markInUse();
            msg.when = when;
            Message p = mMessages;
            boolean needWake;
            if (p == null || when == 0 || when < p.when) {
                // New head, wake up the event queue if blocked.
                //当前队列没有消息,,直接将msg作为队首
                //或者当前队首的时间when大于msg的when时,msg成为新的队首
                msg.next = p;
                mMessages = msg;
                needWake = mBlocked;
            } else {
                // Inserted within the middle of the queue.  Usually we don't have to wake
                // up the event queue unless there is a barrier at the head of the queue
                // and the message is the earliest asynchronous message in the queue.
                needWake = mBlocked && p.target == null && msg.isAsynchronous();
                Message prev;
                //遍历队列,根据when来决定msg插入到队列的位置
                for (;;) {
                    prev = p;
                    p = p.next;
                    if (p == null || when < p.when) {
                        break;
                    }
                    if (needWake && p.isAsynchronous()) {
                        needWake = false;
                    }
                }
                msg.next = p; // invariant: p == prev.next
                prev.next = msg;
            }
    
            // We can assume mPtr != 0 because mQuitting is false.
            if (needWake) {
                nativeWake(mPtr);
            }
        }
        return true;
    }
    
  2. Message next():返回队列中的下一个msg,其中msg的异步性,也是在此段代码中体现的;

    Message next() {
        ......
        
        for (;;) {
            if (nextPollTimeoutMillis != 0) {
                Binder.flushPendingCommands();
            }
    
            nativePollOnce(ptr, nextPollTimeoutMillis);
    
            synchronized (this) {
                // Try to retrieve the next message.  Return if found.
                final long now = SystemClock.uptimeMillis();
                Message prevMsg = null;
                Message msg = mMessages;
                if (msg != null && msg.target == null) {
                    //msg满足上述判断条件后,就会在队列中遍历msg,优先将异步的msg出列,
                    // Stalled by a barrier.  Find the next asynchronous message in the queue.
                    do {
                        prevMsg = msg;
                        msg = msg.next;
                        //此循环直到得到异步的msg才会退出循环
                    } while (msg != null && !msg.isAsynchronous());
                    
                }
                //非异步msg的出列
                if (msg != null) {
                    if (now < msg.when) {
                        // Next message is not ready.  Set a timeout to wake up when it is ready.
                        nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
                    } else {
                        // Got a message.
                        mBlocked = false;
                        if (prevMsg != null) {
                            prevMsg.next = msg.next;
                        } else {
                            mMessages = msg.next;
                        }
                        msg.next = null;
                        if (DEBUG) Log.v(TAG, "Returning message: " + msg);
                        msg.markInUse();
                        return msg;
                    }
                } else {
                    // No more messages.
                    nextPollTimeoutMillis = -1;
                }
    
              ......
        }
    }
    
  3. void quit(boolean safe):提供给looper退出循环的方法(原理:调用此方法后当前队列会返回一个null的msg,looper接收到null的msg后就执行退出循环的操作);

Message

Fields

  1. public int what:一般用于区分不同的msg;

  2. public int arg1,arg2:传递int数据;

  3. public Object obj:传递对象;

  4. Handler target:标记此msg需要发送给哪个handler去处理;

  5. long when:用于决定其在消息队列中的位置;

  6. Runnable callback:handler post方法系列的run回调对象;

  7. Bundle data:将数据存储到bundle中进行传递;

  8. int flags:用于标记当前msg处于什么状态

    1. FLAG_IN_USE:msg正在使用中;
    2. FLAG_ASYNCHRONOUS:异步处理此msg,,在MQueue中会优先让异步的msg出列;
    3. FLAGS_TO_CLEAR_ON_COPY_FROM:?
  9. private static final int MAX_POOL_SIZE = 50;默认消息池的大小为50;

  10. public Messenger replyTo:???

  11. Message next:用于记录当前msg的下一个msg是哪个,消息队列的实质就是通过此属性,使得所有msg之间形成一个链表的关系,这就是消息队列的存在形式,MessageQueue就是管理这个队列的类(入队,出队,退出等操作)

Methods

  1. public static Message obtain():消息池中获取一个msg
  2. public void recycle():回收msg;

Handler

Fields

  1. final Looper mLooper:要创建一个handler对象,必须要为其设置looper;
  2. final MessageQueue mQueue:looper对应的消息队列;
  3. final Callback mCallback:handler处理消息的回调(public boolean handleMessage(Message msg),,通过设置此回调是handler处理msg的方式之一);

Methods

  1. public final boolean post(Runnable r);
  2. public final boolean postAtTime(Runnable r, long uptimeMillis);
  3. public final boolean postDelayed(Runnable r, long delayMillis);
  4. public final boolean sendMessage(Message msg);
  5. public boolean sendMessageAtTime(Message msg, long uptimeMillis):handler发送消息最终都会调用到此方法,内部通过私有方法enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis),再通过mQueue.enqueueMessage(msg, uptimeMillis),最终将消息压入到消息队列中。
  6. public final void removeMessages(int what):将指定的msg移出消息队列(前提是此msg是处于pending等待的状态);
  7. public final void removeCallbacks(Runnable r):具体使用同6;
  8. public final void removeCallbacksAndMessages(Object token):当token参数传入null的时候会将消息队列中的所有正在pending的msg全部移除;
  9. public final Message obtainMessage():从消息池中得到一个空的msg对象(==推荐使用此方式得到msg对象==)
  10. public void dispatchMessage(Message msg):
    /**
     * 
     * 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);
        }
    }
    
    在此方法中可以看到,handler处理消息的机制中,msg的callback是优先级最高的,即实现的Runnable接口中的run方法;其次是handler自身的CallBack回调,最后才是自身的handleMessage(msg)方法;

Constructor

  1. public Handler() ;
  2. public Handler(Callback callback) :添加处理msg的回调;
  3. public Handler(Looper looper):添加looper;
  4. public Handler(Looper looper, Callback callback):
  5. public Handler(boolean async):此设置此handler发送的msg是否需要异步处理
  6. public Handler(Callback callback, boolean async) :
  7. public Handler(Looper looper, Callback callback, boolean async) :
上一篇下一篇

猜你喜欢

热点阅读