Looper
源码位置
Looper.java源码路径为:
android-rk3399/frameworks/base/core/java/android/os/Looper.java
prepare()函数
通过prepare函数可以得知,在一个线程中只会存在一个Looper对象。当多次调用prepare函数时会抛出以下异常。
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {//通过prepare函数可以知道一个线程中只能存在一个Looper对象,否则会抛出以下异常
throw new RuntimeException("Only one Looper may be created per thread");
}
//通过ThreadLocal存放一个Looper对象;
sThreadLocal.set(new Looper(quitAllowed));
}
在主线程中,调用的是prepareMainLooper函数。
我们之所以在activity中不调用prepare()函数就可以直接使用Handler,是因为ActivityThread类的main函数已经帮我们间接调用了prepare函数。ActivityThread的main函数如下图:
Looper()构造函数
在Looper的构造函数中创建一个MessageQueue对象,并获取当前线程对象。源码如下:
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
Loop()函数
Looper通过loop()函数中的死循环不断的从MessageQueue中获取Message,然后调用message.target也就是Handler来调度信息。
public static void loop() {
/**
* public static @Nullable Looper myLooper() {
* return sThreadLocal.get();
* }
* 通过myLooper()函数来获取Looper对象。
*/
final Looper me = myLooper();
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
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获取Handler对象,然后通过handler对象来调度信息
msg.target.dispatchMessage(msg);
} finally {
if (traceTag != 0) {
Trace.traceEnd(traceTag);
}
}
//...此处省去多余代码
}
}
在看源码的时候对ThreadLocal不是很熟悉,特意去看了下实现逻辑;大致整理一下:
ThreadLocal采用的是Map方式将当前线程作为key来存放对象,set函数如下:
Looper的源码到此分析结束,最主要的功能在loop()函数中。