一:前置知识
- Looper有一个变量:ThreadLocal<Looper>
- Thread.currentThread 打破次元壁,在应用层沟通底层,获得当前线程信息
- 每一个Thread,不管是Android的main thread,还是自己定义的thread,总之就是一个Thread,含有一个ThreadLocalMap变量。
- ThreadLocalMap是一个数组,也就是说,每一个Thread都有一个数组。
二:looper的prepare
looper使用prepare可以创建当前线程的looper,没有prepare就使用handler是会报错的。那prepare是如何保证只为当前线程创造一个looper的呢?我先来分析第一次创建。
下面不会放代码,文字叙述:
- 当调用looper.prepare的时候,会调用自己的变量ThreadLocal<Looper>的set(looper)
- 在ThreadLocal里面,获取当前线程myThread(自己的子线程),
- 然后调用myThread的getMap获取到自己的那个数组(上面提到过),然后把新创建的looper放到数组里面。(使用ThreadLocal<Looper>作索引)
也就是说:
ThreadLocal.set(value) 等价于 Thread.table[ThreadLocal.hash()] = value
那么取值呢?
ThreadLocal.get() 等价于 Thread.table[ThreadLocal]
直观上理解就是,一个Thread有一个数组,这个数组有很多ThreadLocal对应的值,有苹果的ThreadLocal,也有西瓜的ThreadLocal,也有Looper的ThreadLocal,每一个ThreadLocal实例只能对应一个值。looper在当前Thread里面放上它对应的looper,拿和取都是用对应的ThreadLocal实例作为索引来取,然后Looper里面就是用它那个final ThreadLocal<Looper>变量。
三:结尾
ThreadLocal其实用处还是蛮大的,如果想要一个变量,在不同线程里面拥有不同值,可以用这个实现。
比较难理解是因为,ThreadLocal的set和get都用了Thread.currentThread()方法,所以一个threadLocal变量可以获取任意一个thread里面数组的值,有点开挂。倒不如说,开发这个类的人挺聪明的。
参考:https://www.kancloud.cn/alex_wsc/android_art/1828635