0. 跨线程的核心原理
线程A通过调用线程B的Handler, 将需要传递的信息或者数据插入到线程B的消息队列中,
然后线程B从消息队列中取出消息,进行处理。
实现了线程 A -> 线程B 的通信。
1.Handler 面试题:

1.1 一个线程可以有多个Handler,
例如主线程中可以创建任意个handler
1.2 一个线程只有一个Looper.
Looper 是一种隐式的实现, ActivityThread.main() 中创建了一个Looper, 并且调用 loop()方法。
public static void main(String[] args) { // 由AMS启动初始化, Message: 进程内的管理,提供初始化
...
Environment.initForCurrentUser(); // 题外话
...
Looper.prepareMainLooper();
...
Looper.loop(); // 不断循环读取消息,处理任务
Looper.prepareMainLooper() 中会调用 Looper.prepare()去创建Looper(唯一创建方式),
保持在ThreadLocal即绑定Thread, 并且一个线程只能创建一个Looper,否则保错
public final class 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));
}
Looper源码分析:
TD: Thread / ThreadLocal/ ThreadLocalMap
主线程 -》 <sThreadLocal, Looper> 线程和Looper 一一对应
1.3 Handler容易造成内存泄漏的原因和解决方法
原因:MessageQueue 持有 Message, Message持有Handler -> Handler 持有this Activity -> Activity 持有大量变量,即大量内存
因此容易造成内存泄漏。 (JVM 垃圾回收机制:可达算法分析)
解决方法:
(1) 在destroy 里面清理Handler中的所有Message
(2)Activity 创建的Handler 声明为static , 用软引用或者弱引用持有activity
1.4 主线程可以创建Handler的原因 以及 在子线程中创建的方式
Looper在应用已启动的时候,即ActivityThread.main() 中,调用了Looper.prepareMainLooper -> loop() 初始化了。因此, 主线程可以直接创建Handler。
如果要在子线程中new Handler, 需要关注多线程同步的问题。
-》 使用HandlerThread, 使用了一个内置锁(开锁和上锁是由JVM完成的): synchronized
public class HandlerThread extends Thread {
@Override
public void run() {
mTid = Process.myTid();
Looper.prepare();
synchronized (this) {
mLooper = Looper.myLooper();
notifyAll();
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
Looper.loop();
mTid = -1;
}
public Looper getLooper() {
if (!isAlive()) {
return null;
}
// If the thread has been started, wait until the looper has been created.
synchronized (this) {
while (isAlive() && mLooper == null) {
try {
wait();
} catch (InterruptedException e) {
}
}
}
return mLooper;
}
}
注意notifyAll(), 这里通知所有等待锁的地方(例如 HandlerThread.getLooper())
wait() 会释放锁,线程可以执行其它内容。
其中Looper.myLooper()
public final class Looper {
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
1.5 子线程维护的Looper,在消息队列没有消息时会退出;主线程则不会退出(AMS 中ActivityThread.main() 启动loop(), 且主要操作由子类Handler完成)
2. Handler工作流程:类似传送带
熟记该类比流程图加深理解
3.Handler主要方法
最终都是调用 MessageQueue.enqueueMessage的方法,进行插入到消息队列的队头(看源码清晰)
3.1 Handler 的关键点 (跟踪源码)
Looper.loop() 从消息队列里取出Message, 最终回调Handler.handleMessage