7.2 第一步:Looper线程准备阶段
本节分析Looper线程的第一步操作:Looper线程准备阶段。这个阶段由Looper.prepare方法完成,该方法位于frameworks/base/core/java/android/os/Looper.java中,代码如下:
public class Looper{
//定义一个线程局部对象存储Looper对象
static final ThreadLocal<Looper>sThreadLocal=new ThreadLocal<Looper>();
private static Looper sMainLooper;//guarded by Looper.class
final MessageQueue mQueue;
final Thread mThread;
volatile boolean mRun;
private Printer mLogging;
//将当前线程初始化为一个Looper线程,进入线程准备阶段
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");
}
/*创建Looper对象并存入sThreadLocal,这样每个调用
prepare方法的线程将创建本线程唯一的Looper对象/
sThreadLocal.set(new Looper(quitAllowed));
}
public static Looper myLooper(){//用于返回当前线程创建的Looper对象
return sThreadLocal.get();
}
prepare方法会调用其重载方法创建一个Looper对象,并将其存入线程局部变量sThreadLocal中。sThreadLocal是ThreadLocal类型的变量,保证每个线程中都有该Looper对象的独立副本。
创建Looper对象时,会首先判断sThreadLocal线程局部变量中是否已经存在一个Looper对象,如果存在便会抛出运行时异常,因此在当前线程中多次调用prepare方法会导致线程异常退出,所以Looper对象是线程唯一的。
综上所述,prepare方法创建了一个线程独立且唯一的Looper对象,如果要访问这个Looper对象,只需要调用myLooper方法。
创建Looper对象的过程涉及很多步骤,接下来分步分析。
7.2.1 创建Java层的Looper对象
首先分析Java层Looper对象的构造函数,代码如下:
private Looper(boolean quitAllowed){//参数quitAllowed为true
mQueue=new MessageQueue(quitAllowed);
mRun=true;
mThread=Thread.currentThread();
}
Looper在构造函数中创建了MessageQueue对象,并将其存入成员变量mQueue中,然后将mRun赋值为true,表示当前线程处于run状态,最后在成员变量mThread中存储当前线程。
创建Java层Looper对象的同时创建了Java层的MessageQueue对象,接下来分析MessageQueue的创建过程。