1

Handler

handler是和线程MessageQueue队列关联发送和处理Message和Runnable的对象。

1.发送Runnable方法如下:

  • post(Runnable)
  • postAtTime(Runnable, long)
  • postDelayed(Runnable, long)

2.发送Message方法如下:

  • sendEmptyMessage(int)
  • sendMessage(Message)
  • sendMessageAtTime(Message, long)
  • sendMessageDelayed(Message, long)

要注意的是handler发送Runnable对象方法实际上是调用SendMessage方法。
直接查看源码,Runnable作为入参到getPostMessage转换成Message对象,Runnable赋值给Message的callback,callback何用等会再讲。

    public final boolean post(Runnable r)
    {
       return  sendMessageDelayed(getPostMessage(r), 0);
    }

    private static Message getPostMessage(Runnable r) {
        Message m = Message.obtain();
        m.callback = r;
        return m;
    }

3.dispatchMessage

Handler的handleMessage是通过dispatchMessage调用的,所以先讲它。handler接收Message一共通过三种方式。

    public void dispatchMessage(Message msg) {
        if (msg.callback != null) {
            handleCallback(msg);
        } else {
            if (mCallback != null) {
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
            handleMessage(msg);
        }
    }
  • 若msg的callBack不为空,调用Message的Runnable的run方法<span id = "Message_Runnable"></span>
    private static void handleCallback(Message message) {
        message.callback.run();
    }
  • 若Handler的mCallback接口回调不为空
    public interface Callback {
        public boolean handleMessage(Message msg);
    }
  • 最后调用handleMessage
    /**
     * Subclasses must implement this to receive messages.
     */
    public void handleMessage(Message msg) {
    }

4.接收Message

  • handleMessage(Message)

所以没有接收Runnable方法,也就知道为什么要把发送的Runnable转成Message了。

5.注意!!

在子线程中创建Handler必需它的mLooper不能为空。这点应该都比较清楚,Handler的构造函数中对mLooper是否为空做了判断,若为空则抛出一个异常。所以在子线程中创建Handler之前先调用Looper.prepare()创建Looper以及实例化Looper的MessageQueue和Thread。

Looper

Looper是用于在Thread中运行消息队列的类。Thread默认不关联Looper。
1.prepare

在线程中调用prepare方法运行loop。
sThreadLocal.get()获取Looper,若为空则去new Looper()。

    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.set(new Looper(quitAllowed));
    }

2.loop

让Looper进入循环处理MessageQueue中的Meessage。loop方法很长里面主要有for(;;)做线程阻塞不断从queue中拿Message分发给Hanlder去处理。具体在msg.target.dispatchMessage(msg)。msg.target对象就Hanlder。看这

for (;;) {
            Message msg = queue.next(); // might block
            if (msg == null) {
                // No message indicates that the message queue is quitting.
                return;
            }
            ...省略部分代码

            final long slowDispatchThresholdMs = me.mSlowDispatchThresholdMs;

            final long traceTag = me.mTraceTag;
            if (traceTag != 0 && Trace.isTagEnabled(traceTag)) {
                Trace.traceBegin(traceTag, msg.target.getTraceName(msg));
            }
            final long start = (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis();
            final long end;
            try {
                msg.target.dispatchMessage(msg);
                end = (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis();
            } finally {
                if (traceTag != 0) {
                    Trace.traceEnd(traceTag);
                }
            }
            ...省略部分代码

            msg.recycleUnchecked();
        }

3.quit

Looper调用loop方法进入死循环,那如何让Looper停止轮询MessageQueue呢。Looper提供quit和quitSafely两个方法退出Looper。

  • quit

quit是非安全的,因为在Looer结束之前可能会存在一些Message还存在MessageQueue中不能被分发。*

Using this method may be unsafe because some messages may not be delivered before the looper terminates.  Consider using {@link #quitSafely} instead to ensure that all pending work is completed in an orderly manner.
  • quitSafely

quit不安全,所以我们使用quitSafely。保证MessageQueue中的Message被及时分发出去。然而延时的Message则不能在quit后分发出去。
Looper的退出都是调用了MessageQueue的quit。

public void quit() {
    mQueue.quit(false);
}
public void quitSafely() {
    mQueue.quit(true);
}

MessageQueue

现在要讲的是MessageQueue。开始之前先把Looper调用quit先讲了。MessageQueue的quit只要说safe控制的removeAllFutureMessagesLocked和removeAllMessagesLocked。
1.quit

    void quit(boolean safe) {
        if (!mQuitAllowed) {
            throw new IllegalStateException("Main thread not allowed to quit.");
        }

        synchronized (this) {
            if (mQuitting) {
                return;
            }
            mQuitting = true;

            if (safe) {
                removeAllFutureMessagesLocked();
            } else {
                removeAllMessagesLocked();
            }

            // We can assume mPtr != 0 because mQuitting was previously false.
            nativeWake(mPtr);
        }
    }
  • 当Looper调用quit非安全退出执行removeAllMessagesLocked,循环MessageQueue将退出前队列中Message全部清空。
    private void removeAllMessagesLocked() {
        Message p = mMessages;
        while (p != null) {
            Message n = p.next;
            p.recycleUnchecked();
            p = n;
        }
        mMessages = null;
    }
  • 当Looper调用quitSafely执行removeAllFutureMessagesLocked,获取当前mMessages的when和SystemClock.uptimeMillis()获取的boot开始到现在的毫秒时间做比较。若Message的时间超过quit的时间则执行非安全退出的quit下的removeAllMessagesLocked。否则将进入循环将MessageQueue要执行的Message分发出去直到MessageQueue清空或者超时(when > now)。
Ps: 所以handler发送Message或者Runnable的延时时间在这里起了作用,根据传入的延时时间做列表排序。
    private void removeAllFutureMessagesLocked() {
        final long now = SystemClock.uptimeMillis();
        Message p = mMessages;
        if (p != null) {
            if (p.when > now) {
                removeAllMessagesLocked();
            } else {
                Message n;
                for (;;) {
                    n = p.next;
                    if (n == null) {
                        return;
                    }
                    if (n.when > now) {
                        break;
                    }
                    p = n;
                }
                p.next = null;
                do {
                    p = n;
                    n = p.next;
                    p.recycleUnchecked();
                } while (n != null);
            }
        }
    }

2.enqueueMessage

前面Handler讲过发送Message,最终都会去执行queue的enqueueMessage方法。

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

MessageQueue排列Message并不是以数组形式,MessageQueue只持有当前的mMessages。新加入到队列的Message会根据它的when判断它在队列的位置。还可以看到若Thread已经dead,则抛出非法异常并把发送的Message回收。

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

Message

<span id = "Message"></span>
最后就是Message了。Message主要成员参数有:long when、Bundle data、Handler target、Runnable callback、Message next。可以看到Message没有前驱只有一个后继Message。所以MessageQueue只存当前mMessages也能找到下一个Message。
1.Runnable
Message有成员参数Runnable。还记得Handler的Post的是Runnable然后转换成Message吗,原来入参的Runnable到这里来了。看这里若Message的Runnable不为空,Handler的dispathMessage可是会走这边的。相当于Handler是Post方法,最后接收的时候是执行Runnable的run方法。

最后

其实讲这么多就是为了摸清楚Handler、Looper、MessageQueue以及Message。整个过程下来理清了Handler作为Message的接收和发送者,将Message插入MessageQueue中。Looper则是作为一个搬运者不停地从MessageQueue中拿取Mssage然后丢给Handler。那么Handler作为Message接收和发送者为何多此一举通过又是Queue又是Looper绕一圈呢?其实其中也有Thread的参与。由于主题主要是Handler机制,所以Thread放在下次有时间单独讲。Handler就是解决进程间通信问题以及异步处理事件,创建子线程做异步操作,把希望返回的内容返回到主线程达到不阻塞UI线程的目的。

  class LooperThread extends Thread {
      public Handler mHandler;
      public void run() {
          Looper.prepare();
          mHandler = new Handler() {
              public void handleMessage(Message msg) {
                  // process incoming messages here
              }
          };
          Looper.loop();
      }
  }

拿了一张比较好理解的Handler机制运行的图片来做结束。图片来源已经在本文最后附上链接
clipboard.png

参考


一个无
110 声望6 粉丝