链接:https://www.zhihu.com/question/19703357/answer/107984017
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
一、google为什么设计这套机制
主要是为了解决在非UI线程中更新UI组件比较麻烦的问题。
二、google如何实现这套机制
UI线程中有一个线程专属的Looper对象,它负责安排所有准备在UI线程上执行的代码。这里有两点技术:实现UI线程专属的Looper对象用到了java的ThreadLocal技术,想深究请直接看ThreadLocal源码,不难,真心不难,当然不看也行,只要知道有这么回事也够,需要时再看。Looper对象通过消息机制接受系统或者应用的其他线程提交的准备在UI线程上执行的代码。提交方式是:以该Looper对象为参数创建一个Handler对象,也可以在UI线程中无参数构建一个Handler对象,此时的Handler对象直接就与UI线程的Looper对象绑定。Handler对象负责向Looper对象提交代码。最直接的提交方法是调用Handler对象的post方法,该方法的参数是一个Runnable对象,代表了要在UI线程上执行的代码。这样的方法简单但是没法传递数据给要执行的代码,因为构造Runnable对象是没有参数的。为此,google提供了另一种提交代码的方法,就是让Handler对象发送一个消息给Looper对象,这个消息中可以包含一定的数据(消息的what域和obj域就是用来包含数据的),要执行的代码就是Handler中的handleMessage方法,该方法会收到发送给Looper的消息,进而可以从中取出数据再执行代码。
以上为原理。
三、一些可以帮助理解原理的细节
因为Looper是给UI线程安排代码的,所以一个UI线程只能有一个Looper对象,否则多个Looper对象都要在UI线程上安排代码,解决冲突就是个大难题。因为Looper对象是线程专属的,所以一个Looper也只能对应一个UI线程。二者是一对一的关系。但是一个Looper对象可以有多个Handler对象向它提交代码,这并不会引起代码冲突。因为Looper对象会线性安排在UI线程上待执行的代码,它通过一个队列管理各个Handler对象提交的代码。Looper对象安排执行代码靠的是它的loop方法。
四、具体使用方法
将一个与UI线程上Looper对象关联的Handler对象传给其他线程,其他线程通过这个对象向UI线程上提交代码。
五、该机制的一般性扩展
实际上,可以为任意一个线程创建一个唯一的Looper对象,这是通过Looper类的静态方法prepare实现的,然后可以用这个Looper对象创建一个或多个Handler对象,然后就可以用这些Handler对象向该线程提交执行代码了,google提供了一个HandlerThread类,就是一个已经实现好了Looper对象的Thread,方便你的使用。
如果觉得本文对你有所帮助,希望不要吝惜你的大拇指,给点个赞。