通过调用Looper的静态方法prepare()为线程创建MessageQueue对象,代码如下:
private static void prepare(boolean quitAllowed) { if (sThreadLocal.get() != null) { throw new RuntimeException("Only one Looper may be created per thread"); } sThreadLocal.set(new Looper(quitAllowed)); }变量sThreadLocal的类型是ThreadLocal,该类的作用是提供“线程局部存储”,那么什么是线程局部存储呢?可以从变量作用域的角度去理解。
常见的变量作用域一般包括以下几种。
线程局部存储:从一个线程中引用该变量,其值总是相同的;而从不同的线程中引用该变量,其值总是不同的。总之,它是一种作用域为线程的变量。
再看Looper.java的prepare()方法。
/** Initialize the current thread as a looper. * This gives you a chance to create handlers that then reference * this looper, before actually starting the loop. Be sure to call * {@link #loop()} after calling this method, and end it by calling * {@link #quit()}. */ public static void prepare() { prepare(true); }这是一个静态方法,其内部会转发到prepare(true),代码如下:
private static void prepare(boolean quitAllowed) { if (sThreadLocal.get() != null) { throw new RuntimeException("Only one Looper may be created per thread"); } sThreadLocal.set(new Looper(quitAllowed)); }注意这句代码:
sThreadLocal.set(new Looper(quitAllowed));sThreadLocal通过调用set()方法,将一个新的Looper对象和调用它的线程绑定在了一起。
接下来看myLooper()方法,代码如下:
/** * Return the Looper object associated with the current thread. Returns * null if the calling thread is not associated with a Looper. */ public static Looper myLooper() { return sThreadLocal.get(); }这也是一个静态方法,通过sTreadLocal的get()方法,获得与调用它的线程所绑定的Looper对象。
总结,不同类型变量的作用域。
变量作用域类型 | 意义 |
函数成员变量 | 仅在函数内部有效 |
类成员变量 | 仅在对象内部有效 |
线程局部存储(TLS)变量 | 在本线程内的任何对象内保持一致 |
静态变量 | 在本进程内的任何对象内保持一致 |
夸进程通信(IPC)变量 | 一般使用Binder进行定义,在所有进程内保持一致。 |