Handler 主要讲的就是 Android 中的消息机制, 其实讲到 Handler 就少不了几个重要的对象, 也就是 Looper , ThreadLocal , MessageQueue

首先看看是如何使用的吧, 我们就简单的从以下入手, Handler 应该也是做 Android 开发中使用的比较频繁的是一个类了

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
Handler handler = new Handler(){
    @Override
    public void handleMessage(Message msg) {
        super.handleMessage(msg);
    }
};

handler.post(new Runnable() {
    @Override
    public void run() {

    }
});

handler.sendEmptyMessage(0);

首先看看 Handler 大致信息, 和构造

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
public class Handler {
  
  	  final Looper mLooper;
      final MessageQueue mQueue;

		 /**
     * 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 方法
            handleMessage(msg);
        }
    }
  
  	// 空参构造
  	public Handler() {
        this(null, false);
    }
  
  	// 含有 Looper 对象构造
    public Handler(Looper looper) {
        this(looper, null, false);
    }

  	// 发送一个 Runnable
    public final boolean post(Runnable r)
    {
       return  sendMessageDelayed(getPostMessage(r), 0);
    }
  
  	// 发送一个 empty 消息
  	public final boolean sendEmptyMessage(int what)
    {
        return sendEmptyMessageDelayed(what, 0);
    }
}

以上省略了部分代码, 我们只要了解到这些大致的信息, 一个 Handler 成员对应着一个 Looper 和 一个 MessageQueue

看看空参构造后面的流程是什么的, 如下

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
public Handler(Callback callback, boolean async) {
        if (FIND_POTENTIAL_LEAKS) {
            final Class<? extends Handler> klass = getClass();
            if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
                    (klass.getModifiers() & Modifier.STATIC) == 0) {
                Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
                    klass.getCanonicalName());
            }
        }

  			// 获取到了 Looper 对象
        mLooper = Looper.myLooper();
  			// 如果Looper 对象为空, 则抛一个异常
        if (mLooper == null) {
            throw new RuntimeException(
                "Can't create handler inside thread that has not called Looper.prepare()");
        }
  			// 获取一个对应的 MessageQueue
        mQueue = mLooper.mQueue;
        mCallback = callback;
        mAsynchronous = async;
}

到了这个地方, 回想一下在我们平时的开发中, 如果是调用了一个空参构造, 然后在子线程创建了一个 Handler , 那么就会报这个错误, 这个是为什么呢 ? 这里有两个疑问点, 一个是为什么子线程中会报错, 然后提示调用 Looper.prepare() 就可以解决问题, 那如果是反过来呢, 为什么主线程中不会报错 ? mLooper 是哪里来的

首先看一下 Looper 大致类的成员信息

1
2
3
4
5
6
7
8
public final class Looper {
      // sThreadLocal.get() will return null unless you've called prepare().
    static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
    private static Looper sMainLooper;  // guarded by Looper.class

    final MessageQueue mQueue;
    final Thread mThread;
}

在这里发现成员变量中创建了一个静态的 sThreadLocal 对象

然后再看看 Looper.prepare() 干了些什么

1
2
3
public static void prepare() {
    prepare(true);
}
1
2
3
4
5
6
7
8
private static void prepare(boolean quitAllowed) {
  	// 如果不为空的情况, 抛异常, 一个线程中只能对应一个 Looper
    if (sThreadLocal.get() != null) {
        throw new RuntimeException("Only one Looper may be created per thread");
    }
  	// 创建了一个 Looper 对象, 并设置给了 sThreadLocal
    sThreadLocal.set(new Looper(quitAllowed));
}

到了这里, Looper.prepare() 的工作就干完了, 这里可以发现有 sThreadLocal 和创建了一个 Looper 对象, 然后我们再看看sThreadLocal.set 都干了些什么

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
public void set(T value) {
  	// 获取到当前的线程
    Thread t = Thread.currentThread();
  	// 通过当前的线程去获取一个 ThreadLocalMap 对象
    ThreadLocalMap map = getMap(t);
    if (map != null)
      	// 当前的 ThreadLocal 设置 value 
        map.set(this, value);
    else
      	// 根据当前的线程去创建 ThreadLocalMap
        createMap(t, value);
}

再看一下 get 方法

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
public T get() {
  	// 获取当前的线程
    Thread t = Thread.currentThread();
  	// 根据当前的线程获取 ThreadLocalMap 对象
    ThreadLocalMap map = getMap(t);
    if (map != null) {
        ThreadLocalMap.Entry e = map.getEntry(this);
        if (e != null) {
            @SuppressWarnings("unchecked")
          	// 获取保存到的值 
            T result = (T)e.value;
            return result;
        }
    }
    return setInitialValue();
}

再贴一个 Looper 中的 myLooper 方法, 其实调用的就是上的 get 方法

1
2
3
public static @Nullable Looper myLooper() {
    return sThreadLocal.get();
}

好吧, 结果绕了一大圈, 到了这里再来看看, 基本上可以解释异常的问题了, 为什么调用 Looper.prepare() 不会抛异常了, 那是因为调用 Looper.prepare() 创建了一个当前线程的 Looper 对象, 也就是子线程的 Looper 对象

这里说到了当前当前线程的对象, 看上面的 ThreadLocal 的 set 和 get 方法就知道了, 其实这个类就是保存当前的线程的数据的, 也就是保证当前线程存在唯一的一份 Looper 对象

还剩下一个问题, 那就是为什么在主线程中创建 Handler 不会抛异常呢 ? 到这里肯定可以猜到, 肯定是 Looper 不为空了, 那么主线程的 Looper 对象又是再哪里创建的呢?

这个其实是在 ActivityThread 主程序的 main 函数入口

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
public static void main(String[] args) {
    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");
    SamplingProfilerIntegration.start();

    // CloseGuard defaults to true and can be quite spammy.  We
    // disable it here, but selectively enable it later (via
    // StrictMode) on debug builds, but using DropBox, not logs.
    CloseGuard.setEnabled(false);

    Environment.initForCurrentUser();

    // Set the reporter for event logging in libcore
    EventLogger.setReporter(new EventLoggingReporter());

    // Make sure TrustedCertificateStore looks in the right place for CA certificates
    final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
    TrustedCertificateStore.setDefaultUserDirectory(configDir);

    Process.setArgV0("<pre-initialized>");

  	// 创建主线程的 Looper 
    Looper.prepareMainLooper();

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

    if (sMainThreadHandler == null) {
      	// 创建了 Handler
        sMainThreadHandler = thread.getHandler();
    }

    if (false) {
        Looper.myLooper().setMessageLogging(new
                LogPrinter(Log.DEBUG, "ActivityThread"));
    }

    // End of event ActivityThreadMain.
    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
  	// 开启消息循环
    Looper.loop();

    throw new RuntimeException("Main thread loop unexpectedly exited");
}

到了这里就可以解析为什么在主线程中创建不会报错了, 因为在 ActivityThread 主程序入口的 main 函数中创建了一个主线程的 Looper 对象

我们再看看 Looper.loop(); 都干了些什么

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
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 对象中的 MessageQueue
    final MessageQueue queue = me.mQueue;

    // Make sure the identity of this thread is that of the local process,
    // and keep track of what that identity token actually is.
    Binder.clearCallingIdentity();
    final long ident = Binder.clearCallingIdentity();

    for (;;) {
      	// 这里开启了一个死循环, 从 MessageQueue 取消息
        Message msg = queue.next(); // might block
        if (msg == null) {
            // No message indicates that the message queue is quitting.
            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);
        }

        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 其实就是 Handler 
          	// 调用 dispatchMessage 最终调用 handleMessage
            msg.target.dispatchMessage(msg);
            end = (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis();
        } finally {
            if (traceTag != 0) {
                Trace.traceEnd(traceTag);
            }
        }
        if (slowDispatchThresholdMs > 0) {
            final long time = end - start;
            if (time > slowDispatchThresholdMs) {
                Slog.w(TAG, "Dispatch took " + time + "ms on "
                        + Thread.currentThread().getName() + ", h=" +
                        msg.target + " cb=" + msg.callback + " msg=" + msg.what);
            }
        }

        if (logging != null) {
            logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
        }

        // Make sure that during the course of dispatching the
        // identity of the thread wasn't corrupted.
        final long newIdent = Binder.clearCallingIdentity();
        if (ident != newIdent) {
            Log.wtf(TAG, "Thread identity changed from 0x"
                    + Long.toHexString(ident) + " to 0x"
                    + Long.toHexString(newIdent) + " while dispatching to "
                    + msg.target.getClass().getName() + " "
                    + msg.callback + " what=" + msg.what);
        }

        msg.recycleUnchecked();
    }
}

大致解释一下 Looper.loop() 中都干了什么, 主要是开启了一个死循环, 然后一直从 MessageQueue 中取 msg 消息, 然后分发给 handleMessage 中, 也就是我们自己创建的 Handler 定义的方法, 这里需要注意的是, 虽然 MessageQueue , 从名字上看像是一个队列的结构, 其实 MessageQueue 它是一个链表的结构

还剩下两个方法 post 和 sendEmptyMessage , 看看这个干了什么

1
2
3
4
5
public final boolean post(Runnable r)
{
   // 发送了一个延时 0 秒的消息
   return  sendMessageDelayed(getPostMessage(r), 0);
}
1
2
3
4
5
6
private static Message getPostMessage(Runnable r) {
  		// 从池子中取出了一个消息
      Message m = Message.obtain();
      m.callback = r;
      return m;
}

到了这个可以发现, 最终 post 的一个 Runnable 对象, 最终包装成了一个 Message , 再看下 sendMessageDelayed

1
2
3
4
5
6
7
public final boolean sendMessageDelayed(Message msg, long delayMillis)
{
    if (delayMillis < 0) {
        delayMillis = 0;
    }
    return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
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);
}
1
2
3
4
5
6
7
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
        msg.target = this;
        if (mAsynchronous) {
            msg.setAsynchronous(true);
        }
        return queue.enqueueMessage(msg, uptimeMillis);
}

再看下 queue.enqueueMessage 方法

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
    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 消息存入了 MessageQueue 当中, sendEmptyMessage 其实调用的方式也是一样的, 这里也就不再贴了

总结

到了这里基本就讲完了大致的流程, 整个消息机制大致是这样的, 首先在主入口 ActivityThread 中的 main 方法中, 创建了主线程的 Looper 对象, 并且开启了消息循环, 不断的往 MessageQueue 中取出消息, 然后进行分发给 handlerMessage 中, 其实当我们 post 一个 runnable 对象 (最终会封装成一个 Message 对象) 和 sendEmptyMessage 最终都是发送一个 Message 到了 MessageQueue 中, 然后 Looper.loop() 不断的取, 符合对应的条件的, 分发给对应的 handler 的 handlerMessage 中, 这样往复循环, 就形成了一个消息机制