一刃鳄、作用
1古拴、在本例中的作用是為每個(gè)線程存儲(chǔ)一個(gè)Looper對(duì)象箩帚。
二、原理
1黄痪、先看一段Handler的構(gòu)造函數(shù)的源碼
198 mLooper = Looper.myLooper();
199 if (mLooper == null) {
200 throw new RuntimeException(
201 "Can't create handler inside thread that has not called Looper.prepare()");
202 }
203 mQueue = mLooper.mQueue;
204 mCallback = callback;
205 mAsynchronous = async;
也就是Handler一個(gè)構(gòu)造函數(shù)在執(zhí)行時(shí)紧帕,會(huì)檢查當(dāng)前線程是不是Looper線程
mLooper = Looper.myLooper();
我們看下Looper的myLooper方法
184 public static @Nullable Looper myLooper() {
185 return sThreadLocal.get();
186 }
再看下Looper的prepare方法
87 private static void prepare(boolean quitAllowed) {
88 if (sThreadLocal.get() != null) {
89 throw new RuntimeException("Only one Looper may be created per thread");
90 }
91 sThreadLocal.set(new Looper(quitAllowed));
92 }
我們?cè)倏聪聅ThreadLocal是什么
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
那ThreadLocal是如何知道當(dāng)前線程的Looper對(duì)象是那個(gè)呢?我們看下ThreadLocal源碼的get方法
142 public T get() {
143 Thread t = Thread.currentThread();
144 ThreadLocalMap map = getMap(t);
145 if (map != null) {
146 ThreadLocalMap.Entry e = map.getEntry(this);
147 if (e != null)
148 return (T)e.value;
149 }
150 return setInitialValue();
151 }
getMap方法實(shí)現(xiàn)
212 ThreadLocalMap getMap(Thread t) {
213 return t.threadLocals;
214 }
187
我們?cè)倏聪聅et方法
179 public void set(T value) {
180 Thread t = Thread.currentThread();
181 ThreadLocalMap map = getMap(t);
182 if (map != null)
183 map.set(this, value);
184 else
185 createMap(t, value);
186 }
再看下createMap方法()實(shí)現(xiàn)
224 void createMap(Thread t, T firstValue) {
225 t.threadLocals = new ThreadLocalMap(this, firstValue);
226 }
綜上桅打,我們可以看出是嗜,每個(gè)Thread都有一個(gè)threadlocals成員變量,這個(gè)變量的類型是ThreadLocalMap挺尾。當(dāng)我們想要傳遞對(duì)象給線程時(shí)鹅搪,需要通過(guò)一個(gè)ThreadLocal對(duì)象把要傳遞的對(duì)象存到目標(biāo)Thread對(duì)象的threadlocals里。所以遭铺,ThreadLocal本質(zhì)上是操作ThreadLocalMaps的一個(gè)工具丽柿。