
本文产生原因是由于我始终相信三点,即:
- 任何技术都是为了解决实际存在的问题而产生的。
- 任何技术的基本原理都是简单明了的。
- 搞清楚一项技术要解决的问题,理解它的基本原理是学习一项技术最好最快最省力的方法。
一、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
,方便你的使用。
如果觉得本文对你有所帮助,希望不要吝惜你的大拇指,给点个赞。
网友评论