深入理解Android的Handler机制

Android的消息机制概述

  • Android的消息机制主要是指Handler的运行机制,Handler的运行需要底层的MessageQueue和Looper的支撑。
  • MessageQueue是消息队列,内部存储了一组消息,以队列的形式对外提供插入和删除的工作。虽然叫消息队列,但它的内部并不是真正地队列,而是采用单链表的数据结构来存储消息列表。
  • Looper是消息循环,MessageQueue只是一个消息的存储单元,而Looper会以无线循环的形式去处理消息。
  • Looper还有个特殊的概念,是ThreadLocal,ThreadLocal并不是线程,它的作用是可以在每个线程中存储数据。Handler创建的时候会采用当前线程的Looper来构造消息循环系统,而ThreadLocal可以在不同的线程中互不干扰的存储并提供数据,通过ThreadLocal可以轻松获取每个线程的Looper。
  • 线程是默认没有Looper的,如果需要用到Handler就必须为线程创建Looper,而主线程ActivityThread被创建时就会初始化Looper,这也就是主线程中默认可以使用Handler的原因。

ThreadLocal的工作原理

ThreadLocal是一个线程内部的数据存储类,通过它可以在指定线程中存储数据,数据存储之后,只有在指定线程中才能获取到数据,对于其他线程来说无法获取数据。

使用例子

1
private ThreadLocal<Boolean> mBooleanThreadLocal = new ThreadLocal<>();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
mBooleanThreadLocal.set(true);
Log.e(TAG, "onCreate: " + mBooleanThreadLocal.get());
new Thread("Thread 1"){
@Override
public void run() {
mBooleanThreadLocal.set(false);
ThreadLocal<Boolean> t = new ThreadLocal<Boolean>();
t.set(true);
Log.e(TAG, "Thread 1 " + mBooleanThreadLocal.get());
Log.e(TAG, "Thread 1 in " + t.get());
}
}.start();
new Thread("Thread 2"){
@Override
public void run() {
Log.e(TAG, "Thread 2 " + mBooleanThreadLocal.get());
}
}.start();

运行结果如下图所示:

在不同线程中访问同一个ThreadLocal对象,但获取到的值不一样。而在同一线程中的两个TheadLocal对象获取到的值也是不一样的,即便泛型值T是相同的。

ThreadLocal的实现

从ThreadLocal的get方法为切入点看源码:

1
2
3
4
5
6
7
8
9
10
public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null)
return (T)e.value;
}
return setInitialValue();
}

getMap方法:

1
2
3
ThreadLocalMap getMap(Thread t) {
return t.threadLocals;
}

t表示当前的线程,从Thread的源码中可以看到,的确是有一个ThreadLocalMap实例:

1
ThreadLocal.ThreadLocalMap threadLocals = null;

每一个Thread都有一个ThreadLocalMap属性,这个属性是类似于HashMap的,ThreadLocalMap是ThreadLocal的一个静态内部类,它以ThreadLocal为键,以属于该线程的资源副本为值。我们可以这样看待ThreadLocal:ThreadLocal是为一组线程维护资源副本的对象,通过它,可以为每一个线程创建资源副本,也可以正确获得属于某一线程的资源副本。
Entry是ThreadLocalMap的静态内部类,代表着ThreadLocalMap的一个键值对,其定义如下所示:

1
2
3
4
5
6
7
8
9
static class Entry extends WeakReference<ThreadLocal> {
/** The value associated with this ThreadLocal. */
Object value;
Entry(ThreadLocal k, Object v) {
super(k);
value = v;
}
}

它继承与弱引用,在ThreadLocalMap类中保持着这样的键值对数组:

1
private Entry[] table;

在ThreadLocal的get()方法中调用e.value方法就可以获取实际的资源副本值。但是如果有一个为空,说明属于该线程的资源副本还不存在,则需要去创建资源副本,从代码中可以看到是调用setInitialValue()方法,其定义如下:

1
2
3
4
5
6
7
8
9
10
private T setInitialValue() {
T value = initialValue();
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
return value;
}

1
2
3
protected T initialValue() {
return null;
}

先调用initialValue方法初始化一个空值,接下来是判断线程的ThreadLocalMap是否为空,不为空就直接设置值(键为this,值为value),为空则创建一个Map,调用方法为createMap(),其定义如下:

1
2
3
void createMap(Thread t, T firstValue) {
t.threadLocals = new ThreadLocalMap(this, firstValue);
}

而ThreadLocalMap的这个构造方法的实现如下:

1
2
3
4
5
6
7
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);
}

实例化table数组用于存储键值对,然后通过映射将键值对存储进入相应的位置。下面是set方法:

1
2
3
4
5
6
7
8
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中的每一个键值对Entry的key是当前的ThreadLocal,传入的是this,使key彼此不同的是ThreadLocal的常量:

1
private final int threadLocalHashCode = nextHashCode();

1
2
3
4
5
private static AtomicInteger nextHashCode = new AtomicInteger();
private static int nextHashCode() {
return nextHashCode.getAndAdd(HASH_INCREMENT);
}

AtomicInteger是一个提供原子操作的Integer类,通过线程安全的方式操作加减,因此可保证多线程下threadLocalHashCode是唯一的,即key值也是唯一的,因此才会出现在上面的例子中同一线程中两个同一泛型的ThreadLocal对象获取到的值也是不一样的。

ThreadLocal的作用

ThreadLocal对Thread的引用全部通过局部变量完成,而没有一个全局变量。而实际的资源副本则存储在Thread的自身的属性ThreadLocalMap中,这说明,其实ThreadLocal只是关联一个Thread和其资源副本的桥梁,并且实际上Thread和资源副本的生命周期是紧密相连的,在线程被回收的时候,其资源副本也会被回收。

MessageQueue的工作原理

MessageQueue主要包含两个操作:插入和读取。读取本身会伴随着删除操作,插入和读取的方法对应着enqueueMessage和next。尽管MessageQueue叫消息队列,但是其内部是通过一个单连标点恶数据结构来维护消息列表的单链表在插入和删除上比较有优势。

enqueueMessage和next方法的:

  • enqueueMessage方法其实就是单链表的插入操作,代码比较多,这里就不贴出了。
  • 而next方法是一个无限循环的方法,如果消息队列中没有消息,那么next方法会一直阻塞在这里。当有新消息到来时,next方法会返回这条消息并将其从单链表中删除。源码如下:
    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
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    Message next() {
    // Return here if the message loop has already quit and been disposed.
    // This can happen if the application tries to restart a looper after quit
    // which is not supported.
    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;
    if (msg != null && msg.target == null) {
    // Stalled by a barrier. Find the next asynchronous message in the queue.
    do {
    prevMsg = msg;
    msg = msg.next;
    } while (msg != null && !msg.isAsynchronous());
    }
    if (msg != null) {
    if (now < msg.when) {
    // Next message is not ready. Set a timeout to wake up when it is ready.
    nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
    } else {
    // Got a message.
    mBlocked = false;
    if (prevMsg != null) {
    prevMsg.next = msg.next;
    } else {
    mMessages = msg.next;
    }
    msg.next = null;
    if (DEBUG) Log.v(TAG, "Returning message: " + msg);
    msg.markInUse();
    return msg;
    }
    } else {
    // No more messages.
    nextPollTimeoutMillis = -1;
    }
    // Process the quit message now that all pending messages have been handled.
    //很关键,根据Looper传进来的标志mQuitting返回null,使Looper的loop方法停止消息循环处理
    if (mQuitting) {
    dispose();
    return null;
    }
    // If first time idle, then get the number of idlers to run.
    // Idle handles only run if the queue is empty or if the first message
    // in the queue (possibly a barrier) is due to be handled in the future.
    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);
    }
    // Run the idle handlers.
    // We only ever reach this code block during the first iteration.
    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);
    }
    }
    }
    // Reset the idle handler count to 0 so we do not run them again.
    pendingIdleHandlerCount = 0;
    // While calling an idle handler, a new message could have been delivered
    // so go back and look again for a pending message without waiting.
    nextPollTimeoutMillis = 0;
    }
    }

Looper的工作原理

Looper的字面意思是“循环者”,它被设计用来使一个普通线程变成Looper线程。所谓Looper线程就是循环工作的线程。在程序开发中,我们经常会需要一个线程不断循环,一旦有新任务则执行,执行完继续等待下一个任务,这就是Looper线程。使用Looper类创建Looper线程很简单:

1
2
3
4
5
6
7
8
9
10
11
12
public class LooperThread extends Thread {
@Override
public void run() {
// 将当前线程初始化为Looper线程
Looper.prepare();
// ...其他处理,如实例化handler
// 开始循环处理消息队列
Looper.loop();
}
}

通过上面两行核心代码,你的线程就升级为Looper线程了

Looper.prepare()


通过上图可以看到,现在你的线程中有一个Looper对象,它的内部维护了一个消息队列MQ。注意,一个Thread只能有一个Looper对象,下面来看一下源码:

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
public class Looper {
// 每个线程中的Looper对象其实是一个ThreadLocal,即线程本地存储(TLS)对象
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
private static Looper sMainLooper; // guarded by Looper.class
// Looper内的消息队列
final MessageQueue mQueue;
// 当前线程
final Thread mThread;
....
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
public static void prepare() {
prepare(true);
}
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
// 试图在有Looper的线程中再次创建Looper将抛出异常
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));
}
.....

通过源码,prepare()背后的工作方式一目了然,其核心就是将looper对象定义为ThreadLocal。ThreadLocal前面已经讲得很详细了。Looper除了prepare方法外,还提供了prepareMainLooper方法,这个方法主要是给主线程也就是ActivityThread创建Looper使用的,其本质也是通过prepare方法来实现的。

Looper.loop()


调用loop方法后,Looper线程就开始真正工作了,它不断从自己的MQ中取出队头的消息(也叫任务)执行。其源码分析如下:

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
public static void loop() {
final Looper me = myLooper();//得到当前线程Looper
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
final MessageQueue queue = me.mQueue;//得到当前looper的MQ
Binder.clearCallingIdentity();
final long ident = Binder.clearCallingIdentity();
// 开始循环
for (;;) {
Message msg = queue.next(); // 取出message,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 traceTag = me.mTraceTag;
if (traceTag != 0 && Trace.isTagEnabled(traceTag)) {
Trace.traceBegin(traceTag, msg.target.getTraceName(msg));
}
try {
// 非常重要!将真正的处理工作交给message的target,即后面要讲的handler
msg.target.dispatchMessage(msg);
} finally {
if (traceTag != 0) {
Trace.traceEnd(traceTag);
}
}
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);
}
// 回收message资源
msg.recycleUnchecked();
}
}

除了prepare()和loop()方法,Looper类还提供了一些有用的方法,比如
Looper.myLooper()得到当前线程looper对象:

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

getThread()得到looper对象所属线程:

1
2
3
public @NonNull Thread getThread() {
return mThread;
}

quit()和quitSafely()方法结束looper循环:

1
2
3
4
5
6
public void quit() {
mQueue.quit(false);
}
public void quitSafely() {
mQueue.quit(true);
}

loop方法是一个死循环,唯一跳出循环的方式是MessageQueue的next方法返回了null,。当Looper的quit方法被调用时,Looper就会调用MessageQueue的quit或者quitSafely方法来通知消息队列退出,当消息队列被标记为退出状态时,它的next方法就会返回null。也就是说,Looper必须退出,否则loop方法就会无限循环下去。loop方法会调用MessageQueue的next方法来获取新消息,否则loop方法就会无限循环下去,当没有消息时,next方法会一直阻塞在那,这也就导致了loop方法一直阻塞在那里。

如果MessageQueue的next方法返回新消息,Looper就会处理这条消息:msg.target.dispatchMessage(msg),这里的msg.target就是发送这条消息的Handler对象,这样Handler发送的消息最终又交到了它的dispatchMessage方法来处理了。但是这里不同的是,Handler的dispatchMessage方法是在创建Handler时所使用的Looper中执行的,这样就成功地将代码逻辑切换到指定的线程中去执行了。

到此为止,你应该对Looper有了基本的了解,总结几点:

  1. 每个线程有且最多只能有一个Looper对象,它是一个ThreadLocal

  2. Looper内部有一个消息队列,loop()方法调用后线程开始不断从队列中取出消息执行

  3. Looper使一个线程变成Looper线程。

Handler工作原理

什么是handler?handler扮演了往MQ上添加消息和处理消息的角色(只处理由自己发出的消息),即通知MQ它要执行一个任务(sendMessage),并在loop到自己的时候执行该任务(handleMessage),整个过程是异步的

Handler初始化

handler创建时会关联一个looper,默认的构造方法将关联当前线程的looper,不过这也是可以set的。默认的构造方法:

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
public class handler {
final Looper mLooper;// 关联的looper
final MessageQueue mQueue;// 关联的MQ
final Callback mCallback;
.....
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不能为空,即该默认的构造方法只能在looper线程中使用
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread that has not called Looper.prepare()");
}
// 重要!!!直接把关联looper的MQ作为自己的MQ,因此它的消息将发送到关联looper的MQ上
mQueue = mLooper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
public Handler(Looper looper, Callback callback, boolean async) {
mLooper = looper;
mQueue = looper.mQueue;
mCallback = callback;
mAsynchronous = async;
}

下面我们就可以为之前的LooperThread类加入Handler:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class LooperThread extends Thread {
private Handler handler1;
private Handler handler2;
@Override
public void run() {
// 将当前线程初始化为Looper线程
Looper.prepare();
// 实例化两个handler
handler1 = new Handler();
handler2 = new Handler();
// 开始循环处理消息队列
Looper.loop();
}
}

加入handler后的效果如下图:

可以看到,一个线程可以有多个Handler,但是只能有一个Looper!

Handler发送消息

有了handler之后,我们就可以使用 post(Runnable), postAtTime(Runnable,long),postDelayed(Runnable,long),sendEmptyMessage(int), sendMessage(Message),sendMessageAtTime(Message, long)和 sendMessageDelayed(Message, long)这些方法向MQ上发送消息了。光看这些API你可能会觉得handler能发两种消息,一种是Runnable对象,一种是message对象,这是直观的理解,但其实post发出的Runnable对象最后都被封装成message对象了,见源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public final boolean postAtTime(Runnable r, long uptimeMillis)
{
return sendMessageAtTime(getPostMessage(r), uptimeMillis);
}
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发出的message有如下特点:

  1. message.target为该handler对象,这确保了looper执行到该message时能找到处理它的handler,即loop()方法中的关键代码

    1
    msg.target.dispatchMessage(msg);
  2. post发出的message,其callback为Runnable对象

Handler处理消息

消息的处理是通过核心方法dispatchMessage(Message msg)与钩子方法handleMessage(Message msg)完成的,见源码

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
// 处理消息,该方法由looper调用
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
// 如果message设置了callback,即runnable消息,处理callback!
handleCallback(msg);
} else {
// 如果handler本身设置了callback,则执行callback
if (mCallback != null) {
/* 这种方法允许让activity等来实现Handler.Callback接口,避免了自己编写handler重写handleMessage方法。见http://alex-yang-xiansoftware-com.iteye.com/blog/850865 */
if (mCallback.handleMessage(msg)) {
return;
}
}
// 如果message没有callback,则调用handler的钩子方法handleMessage
handleMessage(msg);
}
}
// 处理runnable消息
private final void handleCallback(Message message) {
message.callback.run(); //直接调用run方法!
}
// 由子类实现的钩子方法
public void handleMessage(Message msg) {
}

可以看到,除了handleMessage(Message msg)和Runnable对象的run方法由开发者实现外(实现具体逻辑),handler的内部工作机制对开发者是透明的。这正是handler API设计的精妙之处!

Handler消息循环机制总结

Handler的特点

  1. handler可以在任意线程发送消息,这些消息会被添加到关联的MQ上。

  2. handler是在它关联的looper线程中处理消息的。

这就解决了android最经典的不能在其他非主线程中更新UI的问题。android的主线程也是一个looper线程(looper在android中运用很广),我们在其中创建的handler默认将关联主线程MQ。因此,利用handler的一个solution就是在activity中创建handler并将其引用传递给worker thread,worker thread执行完任务后使用handler发送消息通知activity更新UI。(过程如图)

主线程的消息循环

Android的主线程是ActivityThread,主线程的入口方法为main,在main方法中系统会通过Looper.prepareMainLooper来创建主线程的Looper以及MessageQueue,并通过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
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.prepareMainLooper();
ActivityThread thread = new ActivityThread();
thread.attach(false);
if (sMainThreadHandler == null) {
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还需要一个Handler来和消息队列进行交互,这个Handler就是ActivityThread.H,它内部定义了一组消息类型,主要包含了四大组件的启动和停止等过程。如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
private class H extends Handler {
public static final int LAUNCH_ACTIVITY = 100;
public static final int PAUSE_ACTIVITY = 101;
public static final int PAUSE_ACTIVITY_FINISHING= 102;
public static final int STOP_ACTIVITY_SHOW = 103;
public static final int STOP_ACTIVITY_HIDE = 104;
public static final int SHOW_WINDOW = 105;
public static final int HIDE_WINDOW = 106;
public static final int RESUME_ACTIVITY = 107;
public static final int SEND_RESULT = 108;
public static final int DESTROY_ACTIVITY = 109;
public static final int BIND_APPLICATION = 110;
public static final int EXIT_APPLICATION = 111;
public static final int NEW_INTENT = 112;
public static final int RECEIVER = 113;
public static final int CREATE_SERVICE = 114;
public static final int SERVICE_ARGS = 115;
public static final int STOP_SERVICE = 116;
.......
}

ActivityThread通过ApplicationThread和AMS进行进程间通信,AMS以进程间通信的方式完成ACtivityThread的请求后会回调ApplicationThread中Binder方法,然后ApplicationThread会向H发送消息,H收到消息后会将ApplicationThread中的逻辑切换到ActivityThread中去执行,即切换到主线程中去执行。这个过程就是主线程的消息循环模型。