ThreadLocal
往下看之前,需要了解一下Java的ThreadLocal类,可参考博文:
Looper、Handler和MessageQueue
我们分析一下之前的这段代码,查看一下Handler机制中,Handle、Looper和MessageQueue之间到底是什么关系
class WorkerThread extends Thread { @Override public void run() { super.run(); Looper.prepare(); handler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); Log.d("TTTT", "handleMessage:" + Thread.currentThread().getName()); int i = msg.what; Log.d("TTTT", "收到了消息对象:" + i); } }; Looper.loop(); } }
1. 首先执行 Looper.prepare() ;
查看Looper的源代码,路径为:sources\android-19\android\os\Looper.java
首先,Looper类的几个成员变量
// sThreadLocal.get() will return null unless you‘ve called prepare(). static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>(); private static Looper sMainLooper; // guarded by Looper.class final MessageQueue mQueue; final Thread mThread;
这就表明,每一个Looper对象,都与一个消息队列(MessageQueue)相对应,同时也与一个线程(Thread)相对应。
当我们调用Looper的prepare()方法的时候,执行如下代码:
public static void prepare() { 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)); }
从上面的代码可以看出,当执行了Looper.prepare()之后,会先调用ThreadLocal的get方法,判断是否已经存在以当前线程为键的键值对,如果已经存在,则抛出异常 “Only one Looper may be created per thread” 。如果不存在,则执行 sThreadLocal.set(new Looper(quitAllowed)) ;新建一个Looper对象,存入ThreadLocal中。
private Looper(boolean quitAllowed) { mQueue = new MessageQueue(quitAllowed); mThread = Thread.currentThread(); }
可以看出,创建Looper对象的同时,新建了一个MessageQueue对象,赋值给Looper对象的mQueue属性,将当前线程,赋值给Looper的mThread属性。
2. 接下来执行
handler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); Log.d("TTTT", "handleMessage:" + Thread.currentThread().getName()); int i = msg.what; Log.d("TTTT", "收到了消息对象:" + i); } };
实例化一个Handler对象,执行其handleMessage方法,查看Handler的源码,路径:sources\android-19\android\os\Hnadler.java
可以看到Handler类有如下成员变量
final MessageQueue mQueue; final Looper mLooper; final Callback mCallback; final boolean mAsynchronous; IMessenger mMessenger;
找到其Handler的构造方法
public Handler() { this(null, false); } public Handler(Callback callback, boolean async) { if (FIND_POTENTIAL_LEAKS) { final Class<? extends Handler> klass = getClass(); if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) && (klass.getModifiers() & Modifier.STATIC) == 0) { Log.w(TAG, "The following Handler class should be static or leaks might occur: " + klass.getCanonicalName()); } } mLooper = Looper.myLooper(); if (mLooper == null) { throw new RuntimeException( "Can‘t create handler inside thread that has not called Looper.prepare()"); } mQueue = mLooper.mQueue; mCallback = callback; mAsynchronous = async; }
调用了Looper的 myLooper() 方法赋值给mLooper
mLooper = Looper.myLooper();
我们查看Looper.java
public static Looper myLooper() { return sThreadLocal.get(); }
发现将当前线程为键的Looper对象从ThreadLocal中取出并返回,所以,在创建Handler对象的时候,Handler对象的拿到了之前创建的Looper对象
if (mLooper == null) { throw new RuntimeException( "Can‘t create handler inside thread that has not called Looper.prepare()"); }
如果拿到的Looper对象为空,则抛出异常 “Can‘t create handler inside thread that has not called Looper.prepare()” 告知用户在没有调用Looper.preapre()之前,不能创建Handler对象。
mQueue = mLooper.mQueue; mCallback = callback; mAsynchronous = async;
然后将Looper对象的mQueue给Handler的mQueue。
这样,就将Thread、Handler、Looper、MessageQueue联系起来了。