Android之Handler

Handler的整体流程

  • Handler发送消息消息是通过 MessageQueue 中的 enqueueMessage()方法加入消息队列中的,并 且它在放入中就进行好排序,链表头的延迟时间小,尾部延迟时间最大
  • Looper.loop()通过 MessageQueue 中的 next()去取消息。
  • MessageQueue 中的 next()如果当前链表头部消息是延迟消息,则根据延迟时间进行消息队列会 阻塞,不返回给 Looper message,直到时间到了,返回给 message
  • 如果在阻塞中有新的消息插入到链表头部则唤醒线程,MessageQueue 的nativeWake()唤醒
  • 将新消息交给回调给 handler 中的 handleMessage 后,继续调用 MessageQueue 的 next()方法,如果刚刚的延迟消息还是时间未到,则计算时间 继续阻塞。

1 Handler发送消息

1.1 Handler在主线程发送消息

不论是sendMessagesendEmptyMessage还是sendMessageDelayed最终都会调用enqueueMessage方法

  private boolean enqueueMessage(@NonNull MessageQueue queue, @NonNull Message msg,
            long uptimeMillis) {
        //消息绑定Handler对象
        msg.target = this;
        msg.workSourceUid = ThreadLocalWorkSource.getUid();
        //消息是否异步,true标识异步
        if (mAsynchronous) {
            msg.setAsynchronous(true);
        }
        //执行消息队列的入队方法,uptimeMillis表示消息的发送时间
        return queue.enqueueMessage(msg, uptimeMillis);
    }

1.2 Handler在子线程发送消息

在子线程创建Handler时,需在调用Looper.prepare()Looper.loop()

Looper.java
  准备异步消息发送
  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 是JDK中为解决多线程程序的并发问题提供了一种新的思路。使用这个工具类可以很简洁地编写出优美的多线程程序。这里存放的是Looper对象
        sThreadLocal.set(new Looper(quitAllowed));
    }
  //创建looper的时候,也会创建当前线程的消息队列和标记当前线程线程
  private Looper(boolean quitAllowed) {
        mQueue = new MessageQueue(quitAllowed);
        mThread = Thread.currentThread();
    }

2 Looper取消息

    public static void loop() {
       //拿当前线程的looper对象
        final Looper me = myLooper();
        if (me == null) {
            throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
        }
        //确保Looper.loop()调用时,保证消息队列中的消息需要执行完成
        if (me.mInLoop) {
            Slog.w(TAG, "Loop again would have the queued messages be executed"
                    + " before this one completed.");
        }

        me.mInLoop = true;
        final MessageQueue queue = me.mQueue;

        // 核实当前线程的身份
        Binder.clearCallingIdentity();
        final long ident = Binder.clearCallingIdentity();
        ...
        for (;;) {
            //开始取消息
            Message msg = queue.next(); // might block
            if (msg == null) {
                //无消息的时候会退出
                return;
            }
            final Observer observer = sObserver;
            ...//省略部分
            //消息发送的开始时间
            final long dispatchStart = needStartTime ? SystemClock.uptimeMillis() : 0;
            final long dispatchEnd;
            Object token = null;
            if (observer != null) {
                token = observer.messageDispatchStarting();
            }
            long origWorkSource = ThreadLocalWorkSource.setUid(msg.workSourceUid);
            try {
                //分发给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);
            }
            ...
            final long newIdent = Binder.clearCallingIdentity();
            if (ident != newIdent) {
            //再次校验当前线程的身份
            }
            //释放消息
            msg.recycleUnchecked();
        }
    }

3 MessageQueue的next取消息

      //取消息
      for (;;) {
            if (nextPollTimeoutMillis != 0) {
                Binder.flushPendingCommands();
            }
            //仅唤醒一次
            nativePollOnce(ptr, nextPollTimeoutMillis);

            synchronized (this) {
                // 当前时间
                final long now = SystemClock.uptimeMillis();
                Message prevMsg = null;
                //mMessages 表示当前等待处理的消息
                Message msg = mMessages;
                if (msg != null && msg.target == null) {
                    // 寻找下一条异步消息
                    do {
                        prevMsg = msg;
                        msg = msg.next;
                    } while (msg != null && !msg.isAsynchronous());
                }
                if (msg != null) {
                    if (now < msg.when) {
                        // 下一条消息未准备好,这等待,此时会进入到 Binder.flushPendingCommands()这里
                        nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
                    } else {
                        //当前不是阻塞状态
                        mBlocked = false;
                        if (prevMsg != null) {
                            prevMsg.next = msg.next;
                        } else {
                            mMessages = msg.next;
                        }
                        msg.next = null;
                        msg.markInUse();
                        return msg;
                    }
                } else {
                    //没有更多消息 不需要循环
                    nextPollTimeoutMillis = -1;
                }
                // 空闲的IdleHandler数量
                if (pendingIdleHandlerCount < 0
                        && (mMessages == null || now < mMessages.when)) {
                    pendingIdleHandlerCount = mIdleHandlers.size();
                }
                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) {
                    Log.wtf(TAG, "IdleHandler threw exception", t);
                }

                if (!keep) {
                    synchronized (this) {
                        mIdleHandlers.remove(idler);
                    }
                }
            }
            pendingIdleHandlerCount = 0;
            //不影响下次下次消息的获取,保持的调用Binder.flushPendingCommands()一致。
            nextPollTimeoutMillis = 0;
        }

HandlerThread的使用

        HandlerThread handlerThread = new HandlerThread("xxx");
        handlerThread.start();//Looper.prepare();不用我们再次调用
        //拿到新创建的线程的looper来创建Handler
        Looper looper = handlerThread.getLooper();
        Handler handler2 = new Handler(looper);
        handler2.sendMessage(Message);

小纸片

  • 记住ThreadLocal是用来区分Handler
  • 主线程MessageQueue的next()不仅你会使用,系统的异步刷新UI也会使用
上一篇:Handler原理


下一篇:谈谈Android源码——HandlerThread