Android 程序员在面试的时候被问到频率最高的就是Handler相关的问题,聊到Handler就离不开Looper。那么Android 是如何保证一个线程对应一个Looper的呢。要想弄清楚这个问题,我们只能通过源码找答案。
讲这个问题之前我们先看看Looper是什么时候创建的。
Looper的创建
我们都知道Looper的重要性,但是我们在使用Handler发送和处理消息的时候会new一个Handler,可是为什么没有new Looper()呢。
在Activity的主线程中,Looper是被默认创建的,所以先来看下ActivityThread源码。
图一:ActivityThread main()源码
也就是说在我们的主线程被创建的时候就把Looper()创建好了(6442行) 。
小伙伴们可能有有疑问呢,为什么不是new而是prepare呢?看下图大家就明白啦!
图二:Looper 构造方法
接下来咱们看看prepareMainLooper()干了什么
图二:Looper prepareMainLooper()方法??
图三:?Looper?prepare()方法
图四:Looper?myLooper()方法
prepare()方法里面判断了一下如果ThreadLocal get() 不等于空就抛出异常,否则就set一个Looper(),因此prepare()在同一个线程里面是不能被调用两次的。
重点来了?。?!ThreadLocal 是什么?
我们来看下ThreadLocal都干了啥。
图五:?ThreadLocal set()方法??
图五:?ThreadLocal get()方法??
在set方法里面拿到了当前的线程,然后获取了一个ThreadLocalMap对象,将当前线程作为key,set方法里面的参数作为value 放到ThreadLoaclMap里面.。
图六:ThreadLocalMap
图七:?ThreadLocalMap? set方法
这里set的时候判断如果Map里面有的话就替换赋值。get的时候根据Thread去拿value(在Looper这就是拿到了Looper 对象)??吹秸饫镂颐潜晏獾奈侍饩陀卸饬?。
Looper在创建的时候如果有值会抛出异常,没值的时候就去new,而当我们拿Looper的时候通过当前线程键值对去拿,保证了唯一性。
好啦,Looper唯一性就讲到这里,小伙伴们听懂了吗?
博主第一次写专业知识讲解,喜欢的点个赞加个关注,大家一起进步。(有错误欢迎指出)