简述Handler流水线上的各个“员工”

120 阅读8分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

Handler中员工一览

Handler、Looper、Message、MessageQueue、Thread、ThreadLocal、ThreadLocalMap

ThreadLocal

ThreadLocal提供管理线程内部变量副本功能。以作为key存储在ThreadLocalMap中

主要方法:

   get():获取当前线程里的threadLocalMap,获取存在该map中此ThreadLocal对应的value

       即:获取当前线程中某一变量副本

   set():获取当前线程中的threadLocalMap,传入this和value,存入threadLocalMap

       即:存入当前线程的某一变量副本

源码如下:

class ThreadLocal {

    protected T initialValue() {
        return null;
    }

    ThreadLocalMap getMap(Thread t) {
        //获取目标线程中的ThreadLocalMap
        return t.threadLocals;
    }

    public T get() {
        // 获取当前线程中的ThreadLocalMap
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null) {
            ThreadLocalMap.Entry e = map.getEntry(this);
            if (e != null) {
                //获取此ThreadLocal对应的value
                @SuppressWarnings("unchecked")
                T result = (T)e.value;
                return result;
            }
        }
        //如果目标线程中ThreadLocalMap为null或
        // 此ThreadLocal未作为Key存入目标Map,
        // 进行初始化并返回null
        return setInitialValue();
    }

    private T setInitialValue() {
        //value为null
        T value = initialValue();
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        //初始化并将此key存入map,映射值为null
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
        return value;
    }

    public void set(T value) {
        //获取当前线程的ThreadLocalMap
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        //将此ThreadLocal和对应的value存入map
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
    }

    //初始化目标线程中的ThreadLocalmap
    void createMap(Thread t, T firstValue) {
        t.threadLocals = new ThreadLocalMap(this, firstValue);
    }
}

ThreadLocalMap

ThreadLocalMap是ThreadLocal的静态内部类,被Thread持有,管理线程内部变量副本功能。 内部持有ThreadLocal作为key,object作为value。

具体实现为:

       定义内部类Entry(ThreadLocal, Object),存储映射关系,并且继承WeakReference

       定义Entry[]类型table,持有映射数组

       set() 和 getEntry() 存入 取出映射关系和value

源码如下:

static class ThreadLocalMap {

    static class Entry extends WeakReference> {

        Object value;

        Entry(java.lang.ThreadLocal k, Object v) {
            super(k);
            value = v;
        }
    }

    //数组存储Entry
    private Entry[] table;

    //tab中获取key对应的Entry
    private Entry getEntry(java.lang.ThreadLocal key) {
        int i = key.threadLocalHashCode & (table.length - 1);
        Entry e = table[i];
        if (e != null && e.refersTo(key))
            return e;
        else
            return getEntryAfterMiss(key, i, e);
    }

    //使用传入的key和value生成一个Entry存入tab中
    private void set(java.lang.ThreadLocal key, Object value) {
        Entry[] tab = table;
        int len = tab.length;
        int i = key.threadLocalHashCode & (len-1);
        for (Entry e = tab[i];
             e != null;
             e = tab[i = nextIndex(i, len)]) {
            java.lang.ThreadLocal k = e.get();
            if (k == key) {
                e.value = value;
                return;
            }
            if (k == null) {
                replaceStaleEntry(key, value, i);
                return;
            }
        }
        tab[i] = new Entry(key, value);
        int sz = ++size;
        if (!cleanSomeSlots(i, sz) && sz >= threshold)
            rehash();
    }
}

Thread

Thread线程。持有ThreadLocalMap、当前线程中唯一Looper存在变量threadLocalMap中。

class Thread implements Runnable {
    //默认为null,ThreadLocal中createMap方法为其赋值
    ThreadLocal.ThreadLocalMap threadLocals = null;
}

Looper

轮训消息队列,消息派发功能。被Thread持有。

内部定义静态常量ThreadLocal,以此常量作为key存在thread内部变量threadLocalMap中,保证一个线程内部只有一个looper

主要实现:

       持有并初始化MessageQueue

       构造方法私有 只可通过prepare()方法进行初始化

       prepare():通过threadLocal.get()方法判断当前线程是否已持有Looper,若持有则抛出运行时异常RuntimeException(),否则则new出looper并调用threadLocal.set()存入当前线程

       loop():循环访问MessageQueue.next()方法,在获取到null之前不退出循环,以此不停分发消息队列中新的消息;获取到Message之后,调用Message中Handlel类型的target中dispatchMessage()分发到目标Handler进行消息处理。

       quit(): 调用MessageQueue中的quit,进行退出和资源释放

public final class Looper {

    //定义静态常量ThreadLocal做key,key唯一,则当前线程中只能存入唯一looper
    //会以sThreadLocal作为key,此looper(this)作为value存入Thread中ThreadLocalMap
    static final ThreadLocal sThreadLocal = new ThreadLocal();

    //消息队列
    final MessageQueue mQueue;
    //所在线程
    final Thread mThread;

    //静态方法,用于loop初始化
    public static void prepare() {
        prepare(true);
    }

    //校验此looper是否已存在于当前线程
    private static void prepare(boolean quitAllowed) {
        //存在则抛出异常
        if (sThreadLocal.get() != null) {
            throw new RuntimeException("Only one Looper may be created per thread");
        }
        //否则进行初始化并存入当前线程的ThreadLocalMap
        sThreadLocal.set(new Looper(quitAllowed));
    }

    //私有构造,保证安全
    private Looper(boolean quitAllowed) {
        mQueue = new MessageQueue(quitAllowed);
        mThread = Thread.currentThread();
    }

    //获取当前线程中looper
    public static @Nullable Looper myLooper() {
        return sThreadLocal.get();
    }

    //保留主要代码
    public static void loop() {
        final Looper me = myLooper();
        if (me == null) {
            throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
        }
        for (;;) {
            if (!loopOnce(me, ident, thresholdOverride)) {
                return;
            }
        }
    }

    //保留主要代码
    private static boolean loopOnce(final android.os.Looper me,
                                    final long ident, final int thresholdOverride) {
        //获取message
        Message msg = me.mQueue.next(); // might block
        if (msg == null) {
            // No message indicates that the message queue is quitting.
            return false;
        }
        //target为目标handler,调用dispatchMessage将消息传入
        msg.target.dispatchMessage(msg);
        //回收msg
        msg.recycleUnchecked();
        return true;
    }
    
    //释放资源
    public void quit() {
        mQueue.quit(false);
    }
}

MessageQueue

MessageQueue有序消息队列,持有消息。被Looper和Handler持有,但是仅在Looper中初始化。

主要实现:

      内部持有Message类型变量messages做消息存储,和boolean类型变量mQuiting,做退出标志。

       enqueueMessage():添加消息方法,将Message标记为已用,根据传入时间进行插入排序,存入链表messages中,唤醒循环

       next():无限循环,获取并返回链表messages中的下一个消息。若遇到同步屏障,则轮询链表找出最近一个异步消息并返回;否则,按队列顺序找到第一个消息,若执行时间未到,则陷入休眠,时间到时再唤醒(此处调用native方法),若正常获取到消息并且可以立即直接,则直接返回此消息。若消息队列为空,为空则执行闲时任务,在下一次循环时进入休眠等enqueueMessage()唤醒循环,若已退出,则退出循环,释放资源。

public final class MessageQueue {

    //标记是否可以退出
    private final boolean mQuitAllowed;

    //消息链表
    Message mMessages;

    //退出标记
    private boolean mQuitting;

    //保留主要代码
    boolean enqueueMessage(Message msg, long when) {
        //目标handler不能为空
        if (msg.target == null) {
            throw new IllegalArgumentException("Message must have a target.");
        }

        //可能多个线程发消息
        synchronized (this) {
            //已经退出,直接回收msg
            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.when = when;
            Message p = mMessages;
            boolean needWake; //是否需要唤醒
            if (p == null || when == 0 || when < p.when) {
                // 插入到头部并唤醒:队列为空||延时为0的即时消息||新消息延时比队首消息延时更短
                msg.next = p;
                mMessages = msg;
                needWake = mBlocked;//出队方法next是否被阻塞在pollOnce()处(nextPollTimeoutMillis≠0)
            } else {
                //插入队列中间的唤醒条件:队首为同步屏障消息,且插入的是异步消息
                needWake = mBlocked && p.target == null && msg.isAsynchronous();
                Message prev;
                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;
            }

            // 唤醒线程,nativePollOnce不在阻塞
            if (needWake) {
                nativeWake(mPtr);
            }
        }
        return true;
    }

    Message next() {
        final long ptr = mPtr;/*MessageQueue 的native层地址*/
        if (ptr == 0) {//当消息循环已经退出,则直接返回
            return null;
        }

        int pendingIdleHandlerCount = -1; //待处理闲时handler数量
        int nextPollTimeoutMillis = 0;
        for (;;) {
            nativePollOnce(ptr, nextPollTimeoutMillis); //阻塞 类似Object.wait()
            synchronized (this) {
                final long now = SystemClock.uptimeMillis();
                Message prevMsg = null;
                Message msg = mMessages;
                //如果队首是同步屏障消息,则循环查找最近的异步消息
                if (msg != null && msg.target == null) {
                    do {
                        prevMsg = msg;
                        msg = msg.next;
                    } while (msg != null && !msg.isAsynchronous());
                }
                if (msg != null) {
                    //如果待处理的msg未到处理时间
                    if (now < msg.when) {
                        //更新阻塞时间
                        nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
                    } else {
                        // 是否被阻塞,设置为false,供enqueueMessage()使用
                        mBlocked = false;
                        //如果是异步消息,则在链表中部删除msg
                        if (prevMsg != null) {
                            prevMsg.next = msg.next;
                        } else {
                            //不是异步消息,队首后移
                            mMessages = msg.next;
                        }
                        //置空next
                        msg.next = null;
                        msg.markInUse();
                        return msg;
                    }
                } else {
                    // 队列中没有msg,设为-1,下个for循环时线程阻塞
                    nextPollTimeoutMillis = -1;
                }

                /*------------------------------空闲handler处理----------------------------------*/
                /* Idlehandles仅在队列为空或队首消息时机未到时才运行*/
                //获取闲时任务量
                if (pendingIdleHandlerCount < 0
                        && (mMessages == null || now < mMessages.when)) {
                    pendingIdleHandlerCount = mIdleHandlers.size();
                }
                //如果闲时任务为空则跳入下次循环
                if (pendingIdleHandlerCount <= 0) {
                    // No idle handlers to run.  Loop and wait some more.
                    mBlocked = true;
                    continue;
                }

                if (mPendingIdleHandlers == null) {
                    mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];
                }
                mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);
            }

            //执行闲时任务
            for (int i = 0; i < pendingIdleHandlerCount; i++) {
                final IdleHandler idler = mPendingIdleHandlers[i];
                mPendingIdleHandlers[i] = null; // release the reference to the handler
                //执行IdleHandler的queueIdle方法,运行IdelHandler
                idler.queueIdle();
            }
            /*执行完闲时Handler重置闲时计数和下次延迟时间*/
            pendingIdleHandlerCount = 0;
            // 因为执行闲时Handler过程中,可能有新消息enqueue,需要重新检查。
            // 下次延迟时间置0,下次循环时不阻塞。
            nextPollTimeoutMillis = 0;
        }
    }


}

Message

Message消息类,数据结构为单向链表,持有多个参数,由MessageQueue持有,使用享元设计模式。

主要实现:

       Int what:消息标志

       long when:消息执行时间戳

       Handler target:send此消息的handler

       Message next:指向下一消息

       Message sPool:消息池,持有空Message

       int flags: 存储flag信息(存储isUse和isAsynchronous等)

       Messenger replyTo:内部持有handler,用作回调

       obtain():从消息池中获取空message

       recycle():回收消息并存入消息池

public final class Message implements Parcelable {
    public int what;
    public int arg1;
    public int arg2;
    public Object obj;
    public Messenger replyTo;
    public long when;
    Bundle data;
    Handler target;
    int flags;
    Runnable callback;
    Message next;
    private static Message sPool;

    public static android.os.Message obtain() {
        synchronized (sPoolSync) {
            if (sPool != null) {
                android.os.Message m = sPool;
                sPool = m.next;
                m.next = null;
                m.flags = 0; // clear in-use flag
                sPoolSize--;
                return m;
            }
        }
        return new android.os.Message();
    }
    
    public static Message obtain(Handler h, int what) {
        android.os.Message m = obtain();
        m.target = h;
        m.what = what;
        return m;
    }
    
    public void recycle() {
        if (isInUse()) {
            if (gCheckRecycle) {
                throw new IllegalStateException("This message cannot be recycled because it "
                        + "is still in use.");
            }
            return;
        }
        recycleUnchecked();
    }
}

Handler

Handler工具类,发送和处理消息。构造方法需传入looper,获取此looper种MessageQueue并持有。

主要实现:

MessageQueue messageQueue:消息队列,用于存入消息(非new出,是取自Looper中)

       enqueueMessage(): 此方法中将this存入message中target,并调用messageQueue的enqueueMessage()存入消息队列。

       dispatchMessage():获取到将要处理的消息,传入handleMessage(),此方法有Looper调用

       handleMessage():由外部实现,真正对message进行处理。

public class Handler {
    final Looper mLooper;
    final MessageQueue mQueue;
    final Callback mCallback;
    final boolean mAsynchronous;

    public interface Callback {

        boolean handleMessage(@NonNull Message msg);
    }


    //使用者实现此方法
    public void handleMessage(@NonNull Message msg) {

    }

    public Handler(@NonNull Looper looper, @Nullable Callback callback, boolean async) {
        mLooper = looper;
        //获取looper中MessageQueue
        mQueue = looper.mQueue;
        mCallback = callback;
        mAsynchronous = async;
    }

    //looper在loop时调用此方法将消息分发过来
    //执行callback和handleMessage
    public void dispatchMessage(@NonNull Message msg) {
        if (msg.callback != null) {
            handleCallback(msg);
        } else {
            if (mCallback != null) {
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
            handleMessage(msg);
        }
    }

    //在消息池中获取一个Massage
    public final Message obtainMessage() {
        return Message.obtain(this);
    }

    //向队列中添加消息 调用MessageQueue.enqueueMessage()
    private boolean enqueueMessage(@NonNull MessageQueue queue, @NonNull Message msg,
                                   long uptimeMillis) {
        msg.target = this;
        msg.workSourceUid = ThreadLocalWorkSource.getUid();
        if (mAsynchronous) {
            msg.setAsynchronous(true);
        }
        return queue.enqueueMessage(msg, uptimeMillis);
    }
}