Android 如何保证同一个线程Looper的唯一性

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唯一性就讲到这里,小伙伴们听懂了吗?

博主第一次写专业知识讲解,喜欢的点个赞加个关注,大家一起进步。(有错误欢迎指出)

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容