持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第22天,点击查看活动详情
为了活动小家电,接着上篇搞!
什么是Looper?
-
Looper是指不断弹出待Handler处理的任务的结构。即MesseageQueue中的消息和runnables以先进先出的方式不断地被一个一个地检索。
-
顾名思义,Looper 负责迭代。
-
Looper 与 Handler 通信最多。
大多数与消息循环的交互都是通过
Handler
类进行的。 -
Looper的迭代工作是通过loop()函数的无限循环来完成的,与线程类型无关(不管是主线程还是通用线程)。 loop() 函数由一个无限循环组成,该循环重复直到弹出的内容为空。在这个无限循环中,msg.target.dispatchMessage(msg); 通过,Handler,target,处理任务。这里的 dispatch 是指将就绪状态变为运行状态的任务。
/**
* 在这个线程中运行消息队列。 一定要call
* {@link #quit()} 结束循环。
*/
public static void loop() {
final Looper me = myLooper();
final MessageQueue queue = me.mQueue;
// 开始无限循环
for (;;) {
Message msg = queue.next(); // might block
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
try {
msg.target.dispatchMessage(msg);
if (observer != null) {
observer.messageDispatched(token, msg);
}
dispatchEnd = needEndTime ? SystemClock.uptimeMillis() : 0;
} catch (Exception exception) {
if (observer != null) {
observer.dispatchingThrewException(token, msg, exception);
}
throw exception;
} finally {
ThreadLocalWorkSource.restore(origWorkSource);
if (traceTag != 0) {
Trace.traceEnd(traceTag);
}
}
msg.recycleUnchecked();
}
}
Looper 是如何创建的?
默认情况下,无论线程如何,每个 Looper 都存储在创建它的线程的线程本地存储 (TLS)中。MainLooper 主线程的looper ,在API 30之前,MainLooper
是通过在ActivityThread.java的main函数中调用prepareMainLooper()来创建*的,而MainLooper
是通过调用loop()
来操作的。
// ActivityThread.java
public static void main(String[] args) {
Looper.prepareMainLooper();
Looper.loop();
}
但是,在 API 30 之后,prepareMainLooper()
已被弃用,因为它已更改为在 Android 环境中直接创建 MainLooper 的方法 。因此,开发人员不会(像最初那样)参与 MainLooper 的创建,他们只需要通过getMainLooper()
导入它。
另一方面,一般的线程默认是没有Looper的,所以要使用每个线程的Handler,就必须自己创建一个Looper。默认情况下,线程没有与之关联的消息循环。再加上普通线程没有 Looper 的原因,Looper 是 Android 引入的一种结构,但是Android 普通线程默认没有 Looper,因为它使用的是 Java 线程。
创建常规线程的 Looper 的方法是使用 prepare() 函数。此外,与主线程一样,它通过 loop() 调用工作。综上所述,开发者在使用通用线程的地方通过prepare()调用创建Looper,并通过loop()调用使Looper运行**。
// Android Developers : Looper
class LooperThread extends Thread {
public Handler mHandler;
public void run() {
Looper.prepare();
mHandler = new Handler(Looper.myLooper()) {
public void handleMessage(Message msg) {
// 在此处理传入的消息
}
};
Looper.loop();
}
}