Handler消息机制

1.Handler

  • Handler在Android开发中主要用于线程间通信
  • 常见场景如:
    • 在子线程进行耗时操作获取到数据后,需要将数据进行渲染
    • 但是Android系统规定子线程不可以执行界面刷新操作,主线程才可以,所以需要将子线程中的数据交给主线程进行界面刷新
    • 这个时候就需要使用到Handler向主线程发送消息Message,进行线程间消息通信
1.1.Hander的使用
public class HandlerActivity extends AppCompatActivity {

    private TextView textView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_handler);
        textView = findViewById(R.id.tv);
    }

    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            if (msg.what == 100) {
                textView.setText("123456");
            }
        }
    };

    public void onClickTest(View view) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                handler.sendEmptyMessageAtTime(100, 0);
            }
        }).start();
    }
}
1.2 Handler源码解析
public class Handler {
  
    final Looper mLooper;
    final MessageQueue mQueue;
    final Callback mCallback;
  
    public Handler() {
        this(null, false);
    }
  
  //1.构造函数
    public Handler(Callback callback, boolean async) {
        ...
                //1.1.从当前线程获取绑定的Looper对象
        mLooper = Looper.myLooper();
        if (mLooper == null) {
            throw new RuntimeException(
                "Can't create handler inside thread " + Thread.currentThread()
                        + " that has not called Looper.prepare()");
        }
      // 1.2.再从Looper对象中获取消息队列对象mQueue
        mQueue = mLooper.mQueue;
        mCallback = callback;
      //表示当前Handler发送的消息是否是异步消息(默认false是同步消息)
        mAsynchronous = async;
    }
  
    //2.发送消息
    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);
    }
  
  //3.将Message与Handler(target)对象进行绑定
    private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
        msg.target = this;
        if (mAsynchronous) {
            msg.setAsynchronous(true);
        }
      //3.1.将message添加到消息队列MessageQueue中
        return queue.enqueueMessage(msg, uptimeMillis);
    }
  
    //4.消息处理
      public void dispatchMessage(Message msg) {
        if (msg.callback != null) {
            handleCallback(msg);
        } else {
            if (mCallback != null) {
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
            handleMessage(msg);
        }
    }
}

解析:

  • 初始化Handler对象,调用Handler无参构造函数,最后会调用Handler(Callback callback, boolean async)
    • 会先获取当前线程绑定的Looper对象 — Looper.myLooper();
      • 如果Looper对象为null,则说明当前线程没有调用Looper.prepare() 方法进行Looper对象的初始化
    • 接着获取Looper对象中消息队列对象mQueue
  • 这样Handler对象在初始化时,就与当前线程绑定的Looper对象和MessageQueue对象相互关联起来了
  • handler发送消息最后都会调用到sendMessageAtTime方法,接着调用enqueueMessage方法
    • 在该方法中会将Message的target属性设置为当前Handler对象 — msg.target = this;使得Handler发送出发的消息与当前Handler存在对象引用
    • 接着将msg插入到当前Handler所在线程的消息队列中 — queue.enqueueMessage
public final class Looper {
    static final ThreadLocal sThreadLocal = new ThreadLocal();
  
    public static @Nullable Looper myLooper() {
        return sThreadLocal.get();
    }
}

2.Looper

2.1.app程序为什么会一直运行?
  • 实际上Looper内部维护了一个无限循环,保证了APP进程持续进行
2.2.Looper初始化

进程启动入口方法:ActivityThread.main方法

public final class ActivityThread extends ClientTransactionHandler {

    public static void main(String[] args) {
        ...
       // 1.初始化当前线程的Looper对象
        Looper.prepareMainLooper();

        ActivityThread thread = new ActivityThread();
        thread.attach(false, startSeq);

        if (sMainThreadHandler == null) {
            sMainThreadHandler = thread.getHandler();
        }
             // 2.调用Looper.loop()方法开启无限循环
        Looper.loop();
    }
}
2.3.Looper.prepareMainLooper方法
public final class Looper {
    static final ThreadLocal sThreadLocal = new ThreadLocal();
    private static Looper sMainLooper;  // guarded by Looper.class
    final MessageQueue mQueue;
    final Thread mThread;
  
  // Looper构造函数中初始化消息队列MessageQueue对象实例mQueue
    private Looper(boolean quitAllowed) {
        mQueue = new MessageQueue(quitAllowed);
        mThread = Thread.currentThread();
    }
  
    public static @Nullable Looper myLooper() {
        return sThreadLocal.get();
    }
  
    public static void prepareMainLooper() {
      // 1.调用prepare方法,参数false表示不可退出消息队列
        prepare(false);
        synchronized (Looper.class) {
            if (sMainLooper != null) {
                throw new IllegalStateException("The main Looper has already been prepared.");
            }
          //3.myLooper方法获取的就是ThreadLocal中保存的Looper实例,将该值赋值给sMainLooper
            sMainLooper = myLooper();
        }
    }
  
    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");
        }
      // 2.初始化Looper对象实例,并将对象设置到ThreadLocal中
        sThreadLocal.set(new Looper(quitAllowed));
    }
  
    public static Looper getMainLooper() {
        synchronized (Looper.class) {
            return sMainLooper;
        }
    }
}

解析:

  • prepareMainLooper方法中调用了prepare方法创建Looper对象,并将初始化后的Looper对象设置到线变量sThreadLocal中,使创建的Looper对象与当前线程进行绑定
    • sThreadLocal.set(new Looper(quitAllowed));
  • 接着调用myLooper方法,从sThreadLocal中取出Looper对象并赋值给sMainLooper变量
  • 在prepare方法中,会判断sThreadLocal中是否已经绑定过Looper对象,如果之前绑定过则抛出异常
    • 确保在一个线程中Looper.prepare方法只能被调用1次
    • Looper的构造函数在一个线程中只能被调用1次
    • MessageQueue在一个线程中只会被初始化1次
  • 也就是说UI线程中只会存在1个MessageQueue对象,后续通过Handler发送的消息都会被发送到这个MessageQueue中
2.4.Looper.loop方法
  • Looper主要工作就是不断从MessageQueue中取出Message,然后处理Message中指定的任务
  • ActivityThread的main方法中:
    • 先调用了Looper.prepareMainLooper()方法,初始化当前线程的Looper对象
    • 接着调用Looper.loop方法开启无限循环,Looper的主要功能就是在这个循环中完成的
public final class Looper {
  public static void loop() {
        //1.获取Looper的消息队列对象mQueue
        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;

        boolean slowDeliveryDetected = false;
    
            // 2.使用for死循环,不断从消息队列queue中获取Message - Message msg = queue.next();
        for (;;) {
            Message msg = queue.next(); // might block = 可能会阻塞
            if (msg == null) {
                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);
            }
            ...
            try {
              // 3.获取Message的target,该值是Handler对象实例
              // 接着调用Handler的dispatchMessage方法进行消息分发
                msg.target.dispatchMessage(msg);
                dispatchEnd = needEndTime ? SystemClock.uptimeMillis() : 0;
            } finally {
                if (traceTag != 0) {
                    Trace.traceEnd(traceTag);
                }
            }
            ...
            if (logging != null) {
                logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
            }
            ...
            msg.recycleUnchecked();
        }
    }
}

解析:

  • loop方法中执行了一个死循环,这也是一个Android App进程能够持续运行的原因
  • 在循环中不断调用MessageQueue的next方法取出Message消息
  • 如果message不为null,则获取Message的target,该值是Handler对象实例,然后调用Handler的dispatchMessage方法进行消息分发
2.5.从消息队列中获取消息MessageQueue.next()
Message next() {
    final long ptr = mPtr;
    if (ptr == 0) {
        return null;
    }

    int pendingIdleHandlerCount = -1; // -1 only during first iteration
    int nextPollTimeoutMillis = 0;
    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;
          // 头节点msg为同步屏障消息(msg.target == null),
          // 找到后面第一个异步消息(!msg.isAsynchronous()),记为msg
            if (msg != null && msg.target == null) {
                do {
                    prevMsg = msg;
                    msg = msg.next;
                } while (msg != null && !msg.isAsynchronous());
            }
            if (msg != null) {
                if (now < msg.when) {
                  // msg的执行时间大于当前时间,不执行,进行休眠(nextPollTimeoutMillis毫秒)
                    nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
                } else {
                  // 从队列中删除需要处理的msg消息,并返回
                    mBlocked = false;
                    if (prevMsg != null) {
                        prevMsg.next = msg.next;
                    } else {
                        mMessages = msg.next;
                    }
                    msg.next = null;
                    msg.markInUse();
                    return msg;
                }
            } else {
              //没有消息需要执行
                nextPollTimeoutMillis = -1;
            }

            if (mQuitting) {
                dispose();
                return null;
            }

          //处理IdleHandler消息
            if (pendingIdleHandlerCount < 0
                    && (mMessages == null || now < mMessages.when)) {
                pendingIdleHandlerCount = mIdleHandlers.size();
            }
          //也没有IdleHandler消息需要处理,直接continue获取下一个msg
          //或者休眠nextPollTimeoutMillis)
            if (pendingIdleHandlerCount <= 0) {
                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

            boolean keep = false;
            try {
                keep = idler.queueIdle();
            } catch (Throwable t) {
            }

            if (!keep) {
                synchronized (this) {
                    mIdleHandlers.remove(idler);
                }
            }
        }

        pendingIdleHandlerCount = 0;
        nextPollTimeoutMillis = 0;
    }
}
  • MessageQueue的next方法的作用是从消息队列中获取一个可用的Message消息,如果没有则调用nativePollOnce方法进行休眠
    • 消息队列MessageQueue中的消息有三种类型:
      • 同步屏障消息(msg.target == null)
      • 异步消息:msg.isAsynchronous()
      • 同步消息:
  • next方法会先从队列的头节点开始获取消息,如果头节点消息为同步屏障消息,则会往后遍历获取后面第一个异步消息
            Message prevMsg = null;
            Message msg = mMessages;
          // 头节点msg为同步屏障消息(msg.target == null),
          // 找到后面第一个异步消息(!msg.isAsynchronous()),记为msg
            if (msg != null && msg.target == null) {
                do {
                    prevMsg = msg;
                    msg = msg.next;
                } while (msg != null && !msg.isAsynchronous());
            }
  • 获取到需要执行的消息后,如果当前时间还没有消息的执行时间,则计算出时间差值nextPollTimeoutMillis,并进行休眠
  • 如果刚好到msg消息执行的when时间,则将该msg消息从队列中删除,并将该消息返回给Looper.loop()方法进行分发

2.6.消息分发流程:

public class Handler {

    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的run方法
    private static void handleCallback(Message message) {
        message.callback.run();
    }
  
    public void handleMessage(Message msg) {
    }
}
  • 消息分发入口:dispatchMessage
    • 先判断Message是否设置了callback,该callback是Runnable接口,最后会调用实现类的run方法
    • 如果callback为空,则先判断Handler是否设置了mCallback,并调用其回调方法
    • 如果都没有,则调用Handler的handleMessage方法

3.MessageQueue消息队列

public class Handler {
  
    public final boolean post(Runnable r){
       return  sendMessageDelayed(getPostMessage(r), 0);
    }
    public final boolean postDelayed(Runnable r, long delayMillis){
        return sendMessageDelayed(getPostMessage(r), delayMillis);
    }
  
    private static Message getPostMessage(Runnable r) {
        Message m = Message.obtain();
        m.callback = r;
        return m;
    }
  
    public final boolean sendMessage(Message msg){
        return sendMessageDelayed(msg, 0);
    }
    public final boolean sendEmptyMessage(int what){
        return sendEmptyMessageDelayed(what, 0);
    }
    public final boolean sendEmptyMessageDelayed(int what, long delayMillis) {
        Message msg = Message.obtain();
        msg.what = what;
        return sendMessageDelayed(msg, delayMillis);
    }
    public final boolean sendMessageDelayed(Message msg, long delayMillis){
        if (delayMillis < 0) {
            delayMillis = 0;
        }
        return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
    }
  
    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);
    }
  
    private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
        msg.target = this;
        if (mAsynchronous) {
            msg.setAsynchronous(true);
        }
        return queue.enqueueMessage(msg, uptimeMillis);
    }
}

解析:

  • Handler发送消息有两种方式:
    • setMessage:
    • post:post方法中调用Message.obtain()构造一个Message对象,并为msg的callback赋值r
  • Handler方法消息的方法最终都会调用sendMessageAtTime方法
    • 该方法会先获取当前线程的消息队列mQueue
    • 然后给msg的target属性设置值,该值为当前Handler对象(msg.target = this;)
    • 接着调用消息队列queue的enqueueMessage方法将msg加入消息队列中
3.2.消息入队列
public final class MessageQueue {
  
    private final boolean mQuitAllowed;
    private long mPtr; // used by native code
    Message mMessages;  //消息队列的头节点(链表结构)
  
    boolean enqueueMessage(Message msg, long when) {
      // 1.判断msg的target值,该值为Hanlder对象,不能为空
        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的状态为正在使用中
            msg.markInUse();
            msg.when = when;
            Message p = mMessages;
            boolean needWake;
          // 参数when为消息入队列的时间,如果队列为空(p==null),或需要插入消息的时间在头节点消息前执行
            if (p == null || when == 0 || when < p.when) {
                // msg作为新的头节点,并将msg的next指向原先的头节点p
                msg.next = p;
                mMessages = msg;
                needWake = mBlocked;
            } 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插入到p节点前面
                msg.next = p; // invariant: p == prev.next
                prev.next = msg;
            }
            // needWake为true,调用nativeWake方法唤醒
            if (needWake) {
                nativeWake(mPtr);
            }
        }
        return true;
    }
}

解析:

  • enqueueMessage方法,会先判断msg的target对象不能为空,target变量是Handler对象类型,后续从MessageQueue消息队列中获取msg然后调用该Handler对象的dispatchMessage来处理
  • 接着会按照Message的延迟时间when来有序插入到MessageQueue中,消息队列是按照Message的执行时间来排序的链表结构

4.Looper.loop方法为什么不会阻塞主线程

  • Looper.loop方法实际上是一个死循环,但是我们的UI线程并没有被阻塞。是因为在MessageQueue的next方法中调用了nativePollOnce

解析:

  • nativePollOnce方法是一个native方法,调用此方法,主线程会释放CPU资源进入休眠状态,直到下条消息到达或者有事物发生。
  • 通过往pipe管道写端写入数据来唤醒主线程工作,这里采用的epoll机制。

5.同步屏障

  • 主线程工作主要进行界面渲染与用户输入,还有其他操作,而且这些操作都是通过Handler发送消息,消息最后插入到消息队列MessageQueue中
  • 那如何保证界面渲染的消息能够在消息队列中优先执行
5.1.调用渲染操作方法
  • android.view.ViewRootImpl#requestLayout
public final class ViewRootImpl implements ViewParent, {

    public void requestLayout() {
        if (!mHandlingLayoutInLayoutRequest) {
            checkThread();
            mLayoutRequested = true;
            scheduleTraversals();
        }
    }
  
    void scheduleTraversals() {
        if (!mTraversalScheduled) {
            mTraversalScheduled = true;
          //往MessageQueue中发送同步屏障消息
            mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
          // 接着Choreographer类中发送异步消息
            mChoreographer.postCallback(
                    Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
            if (!mUnbufferedInputDispatch) {
                scheduleConsumeBatchedInput();
            }
            notifyRendererOfFramePending();
            pokeDrawLockIfNeeded();
        }
    }
}
  • MessageQueue插入同步消息(msg的target对象为null)
public int postSyncBarrier() {
    return postSyncBarrier(SystemClock.uptimeMillis());
}

private int postSyncBarrier(long when) {
    synchronized (this) {
        final int token = mNextBarrierToken++;
        final Message msg = Message.obtain();
        msg.markInUse();
        msg.when = when;
        msg.arg1 = token;

        Message prev = null;
        Message p = mMessages;
      //从头节点开始查找msg插入的位置
        if (when != 0) {
            while (p != null && p.when <= when) {
                prev = p;
                p = p.next;
            }
        }
        if (prev != null) { // invariant: p == prev.next
            msg.next = p;
            prev.next = msg;
        } else {
            msg.next = p;
            mMessages = msg;
        }
        return token;
    }
}
  • Choreographer的postCallback方法
    private void postCallbackDelayedInternal(int callbackType,
            Object action, Object token, long delayMillis) {
        synchronized (mLock) {
            final long now = SystemClock.uptimeMillis();
            final long dueTime = now + delayMillis;
            mCallbackQueues[callbackType].addCallbackLocked(dueTime, action, token);

            if (dueTime <= now) {
                scheduleFrameLocked(now);
            } else {
                Message msg = mHandler.obtainMessage(MSG_DO_SCHEDULE_CALLBACK, action);
                msg.arg1 = callbackType;
                msg.setAsynchronous(true);
                mHandler.sendMessageAtTime(msg, dueTime);
            }
        }
    }

//发送异步消息
    private void scheduleFrameLocked(long now) {
        if (!mFrameScheduled) {
            mFrameScheduled = true;
            if (USE_VSYNC) {
                if (isRunningOnLooperThreadLocked()) {
                    scheduleVsyncLocked();
                } else {
                    Message msg = mHandler.obtainMessage(MSG_DO_SCHEDULE_VSYNC);
                    msg.setAsynchronous(true);
                    mHandler.sendMessageAtFrontOfQueue(msg);
                }
            } else {
                final long nextFrameTime = Math.max(
                        mLastFrameTimeNanos / TimeUtils.NANOS_PER_MS + sFrameDelay, now);
                Message msg = mHandler.obtainMessage(MSG_DO_FRAME);
                msg.setAsynchronous(true);
                mHandler.sendMessageAtTime(msg, nextFrameTime);
            }
        }
    }
5.2.vsync消息处理
  • android.view.Choreographer.FrameHandler
private final class FrameHandler extends Handler {
    public FrameHandler(Looper looper) {
        super(looper);
    }

    @Override
    public void handleMessage(Message msg) {
        switch (msg.what) {
            case MSG_DO_FRAME:
                doFrame(System.nanoTime(), 0);
                break;
            case MSG_DO_SCHEDULE_VSYNC:
                doScheduleVsync();
                break;
            case MSG_DO_SCHEDULE_CALLBACK:
                doScheduleCallback(msg.arg1);
                break;
        }
    }
}

6.一个线程如何保证只有一个消息队列

  • java.lang.ThreadLocal
  • java.lang.ThreadLocal.ThreadLocalMap
public class ThreadLocal {

      public void set(T value) {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
    }
  
    ThreadLocalMap getMap(Thread t) {
        return t.threadLocals;
    }
  
    void createMap(Thread t, T firstValue) {
        t.threadLocals = new ThreadLocalMap(this, firstValue);
    }
}
  • ThreadLocalMap队列
    static class ThreadLocalMap {

      //节点Entry
        static class Entry extends WeakReference> {
            Object value;
            Entry(ThreadLocal k, Object v) {
                super(k);
                value = v;
            }
        }

        private static final int INITIAL_CAPACITY = 16;
        private Entry[] table;
        private int size = 0;
        private int threshold; // Default to 0

        private void setThreshold(int len) {
            threshold = len * 2 / 3;
        }

        /**
         * Increment i modulo len.
         */
        private static int nextIndex(int i, int len) {
            return ((i + 1 < len) ? i + 1 : 0);
        }

        private static int prevIndex(int i, int len) {
            return ((i - 1 >= 0) ? i - 1 : len - 1);
        }

        //ThreadLocalMap 初始化 -- 内部使用数组保存数据
        ThreadLocalMap(ThreadLocal firstKey, Object firstValue) {
            table = new Entry[INITIAL_CAPACITY];
            int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1);
            table[i] = new Entry(firstKey, firstValue);
            size = 1;
            setThreshold(INITIAL_CAPACITY);
        }

        ...

        //获取数据,key值为ThreadLocal对象
        private Entry getEntry(ThreadLocal key) {
            int i = key.threadLocalHashCode & (table.length - 1);
            Entry e = table[i];
            if (e != null && e.get() == key)
                return e;
            else
                return getEntryAfterMiss(key, i, e);
        }

        private Entry getEntryAfterMiss(ThreadLocal key, int i, Entry e) {
            Entry[] tab = table;
            int len = tab.length;

            while (e != null) {
                ThreadLocal k = e.get();
                if (k == key)
                    return e;
                if (k == null)
                    expungeStaleEntry(i);
                else
                    i = nextIndex(i, len);
                e = tab[i];
            }
            return null;
        }

        //设置数据 -- 对应 sThreadLocal.set(new Looper(quitAllowed));
        private void set(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)]) {
                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();
        }

        //remove
        private void remove(ThreadLocal key) {
            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)]) {
                if (e.get() == key) {
                    e.clear();
                    expungeStaleEntry(i);
                    return;
                }
            }
        }

        //replace 替换
        private void replaceStaleEntry(ThreadLocal key, Object value,
                                       int staleSlot) {
            Entry[] tab = table;
            int len = tab.length;
            Entry e;

            int slotToExpunge = staleSlot;
            for (int i = prevIndex(staleSlot, len);
                 (e = tab[i]) != null;
                 i = prevIndex(i, len))
                if (e.get() == null)
                    slotToExpunge = i;

            for (int i = nextIndex(staleSlot, len);
                 (e = tab[i]) != null;
                 i = nextIndex(i, len)) {
                ThreadLocal k = e.get();

                if (k == key) {
                    e.value = value;
                    tab[i] = tab[staleSlot];
                    tab[staleSlot] = e;
                    if (slotToExpunge == staleSlot)
                        slotToExpunge = i;
                    cleanSomeSlots(expungeStaleEntry(slotToExpunge), len);
                    return;
                }

                if (k == null && slotToExpunge == staleSlot)
                    slotToExpunge = i;
            }

            tab[staleSlot].value = null;
            tab[staleSlot] = new Entry(key, value);

            if (slotToExpunge != staleSlot)
                cleanSomeSlots(expungeStaleEntry(slotToExpunge), len);
        }

        //扩容
        private void resize() {
            Entry[] oldTab = table;
            int oldLen = oldTab.length;
            int newLen = oldLen * 2;
            Entry[] newTab = new Entry[newLen];
            int count = 0;

            for (int j = 0; j < oldLen; ++j) {
                Entry e = oldTab[j];
                if (e != null) {
                    ThreadLocal k = e.get();
                    if (k == null) {
                        e.value = null; // Help the GC
                    } else {
                        int h = k.threadLocalHashCode & (newLen - 1);
                        while (newTab[h] != null)
                            h = nextIndex(h, newLen);
                        newTab[h] = e;
                        count++;
                    }
                }
            }

            setThreshold(newLen);
            size = count;
            table = newTab;
        }
    }
  • 线程Thread类中有一个threadLocals变量,该变量类型为ThreadLocalMap,可以将ThreadLocalMap作为一个键值对类型的数据结构
    • 以ThreadLocal为key值,Object为value值(其中Looper.prepare()方法中Looper对象为value值)
    • ThreadLocal中以Entry[]数组为底层实现,key,value值封装为一个Entry类;tab[i] = new Entry(key, value)
    • 且Entry是弱引用WeakReference的实现类,以ThreadLocal对象做为弱引用类型
总结
  • 消息机制,在主线程启动时(即ActivityThread调用main方法),会调用Looper.prepare()进行Looper对象的初始化,并将Looper对象与当前线程进行相互绑定(通过ThreadLocal进行实现)
  • Looper初始化时,会初始化消息队列MessageQueue,作为Looper对象mQueu的变量
  • 接着调用Looper.loop()方法,在该方法中使用for死循环,不断从MessageQueue中获取消息
  • Handler初始化会获取当前线程的Looper和MessageQueue的对象,通过Handler发送的Message消息最后会插入到消息队列MessageQueue中
  • 在Looper.loop方法中不断获取到Message消息,然后调用msg.target.dispatchMessage方法进行消息分发

你可能感兴趣的:(Handler消息机制)