这个类用于为线程运行一个消息循环. 默认上, 线程是没有与之绑定的消息循环的. 为了创建一个消息循环, 在线程中调用 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>();
ThreadLocal: 线程本地存储区(Thread Local Storage,简称为TLS),每个线程都有自己的私有的本地存储区域,不同线程之间彼此不能访问对方的TLS区域。这里线程自己的本地存储区域存放是线程自己的Looper。具体看下ThreadLocal.java 的源码!
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(); } }