一、主线程和Looper
我们知道android中可以使用Handler向主线程发送消息,来实现线程间的异步通信,AsyncTask内部其实也是使用Handler实现的。
主线程之所以可以接收Handler消息,是因为主线程在启动时,已经创建了Looper对象。
/*** ActivityThread.java ***/
public static void main(String[] args) {
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
thread.attach(false);
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
Looper.loop();
}
二、工作线程使用Looper
而我们如果直接创建一个线程,是无法接收Handler的消息的,需要为该线程创建一个Looper对象才可以。
创建带有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();
}
}
实际上,主线程的Looper创建,和上面的过程是一样一样的。
下面根据这个过程,简单介绍一下Android的Looper机制。
三、Looper机制简介
Android应用程序是通过消息来驱动的,每一个拥有Looper的线程(如主线程),都有一个消息队列,其他线程向消息队列里放入消息,Looper线程不断循环地从消息队列里取出消息并处理。没有消息可处理时,Looper线程就进入阻塞状态,直到有新的消息需要处理时被唤醒。
四、代码位置
基于Android6.0的代码
涉及到的类的代码位置
frameworks/base/core/java/android/os/Handler.java
frameworks/base/core/java/android/os/Message.java
frameworks/base/core/java/android/os/MessageQueue.java
frameworks/base/core/java/android/os/Looper.java
frameworks/base/core/jni/android_os_MessageQueue.cpp
system/core/libutils/Looper.cpp
五、Looper.java简化
package android.os;
public final class Looper {
//为每一个线程维护一个Looper
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
//主线程Looper,每个进程只有一个
private static Looper sMainLooper;
//Looper的消息队列
final MessageQueue mQueue;
//Looper所在的线程
final Thread mThread;
public static void prepare() {
prepare(true);
}
private static void prepare(boolean quitAllowed) {
//同一个线程不能重复创建Looper
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));
}
//创建主线程Looper,由系统调用
public static void prepareMainLooper() {
prepare(false);
synchronized (Looper.class) {
if (sMainLooper != null) {
throw new IllegalStateException("The main Looper has already been prepared.");
}
sMainLooper = myLooper();
}
}
/**
* Returns the application's main looper, which lives in the main thread of the application.
*/
public static Looper getMainLooper() {
synchronized (Looper.class) {
return sMainLooper;
}
}
/**
* Run the message queue in this thread. Be sure to call
* {@link #quit()} to end the loop.
*/
public static void loop() {
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