Looper

这个类用于为线程运行一个消息循环. 默认上, 线程是没有与之绑定的消息循环的. 为了创建一个消息循环, 在线程中调用 prepare 方法来创建一个循环, 之后调用 loop 方法启动循环, 开始处理消息, 直到循环停止.

大多数与 Loop 有关的交互都是通过 Handler 类来实现的.

下面给出一个最典型的实现 Looper 的线程. 使用单独的 prepare 和 loop 来创建一个初始 Handler 来与 Looper 交流:

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();
    }
}

数据结构

ThreadLocal

ThreadLocal 中存放 Looper:

static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();

sMainLooper

MainLooper 整个应用程序里面只有一个. 应用程序的 MainLooper 是由 Android 环境创建的. 因此开发者不应当调用 prepareMainLooper 方法.

private static Looper sMainLooper;

static 修饰符

注意到 sThreadLocal 和 sMainLooper 都是 static 的.

类的 static 成员说明所有的类实例中这两个成员都只有==一份==.

sThreadLocal 这块可以好好看看, 它也是 static 的, 它内部保存到是各个线程的 Looper 实例. ThreadLocal 只有一个接口 get, 每个线程都通过这个方法拿到自己的 Looper.

mQueue

final MessageQueue mQueue;

这个就不是 static 的了, 这是每个 Looper 实例自己有一份的.

MessageQueue 等着单独分析.

这里只要确定一点:== Looper 中包含 MessageQueue 消息队列.==

mThread

final Thread mThread;

这个成员保存了 Looper 实例所处的 Thread 线程的实例.

用到这个实例的地方有:

  • 构造函数中 Thread.currentThread()
  • getThread 获取线程

方法

prepare 系列

将当前线程初始化为 Looper. prepare 给予你机会在 Looper 真正运行之前来创建 Handler 并引用到这个 Looper. 在这之后, 需要调用 loop() 方法来使 Looper 运行, 最后调用 quit() 方法来退出.

prepare 方法有两个, 带参数和不带参数的:

public static void prepare()
private static void prepare(boolean quitAllowed)

还有一个初始化 MainLooper 的:

public static void prepareMainLooper()

MainLooper 和普通 Looper 的初始化进本是类似的, 创建一个 Looper 实例并保存至 ThreadLocal 类型的 sThreadLocal 中. MainLooper 比普通 Looper 再多一步的操作是将 Looper 实例的引用保存到 sMainLooper 成员中.

getter 方法

前面分析了两种 Looper 的创建, 现在来看看它们的获取方法:

  • public static @Nullable Looper myLooper()
  • public static Looper getMainLooper()

一个是获取普通 Looper 的, 一个是获取 MainLooper 的.

loop() 运行循环

代码的实现非常清晰:

public static void loop() {
    // 获取 Looper
    final Looper me = myLooper();
    // 获取消息队列
    final MessageQueue queue = me.mQueue;

    // 死循环
    for (;;) {
        // 获取下一条消息
        Message msg = queue.next(); // 可能会阻塞

        // 消息为空说明队列正在推出, 因此直接退出
        if (msg == null) return;

        // msg.target 是一个 Handler, 因此分发这个消息
        msg.target.dispatchMessage(msg);

        // 回收消息
        msg.recycleUnchecked();
    }
}