Android的消息机制主要是指Handler的运行机制,Handler的运行主要由MessageQueue(消息队列)和Looper(消息循环泵)来支撑。MessageQueue只要储存消息,它是以队列的形式对外提供删除插入的工作,虽然是队列 但它不是真正的队列,底部还是采用的单链表的数据结构来储存信息列表的。由于MessageQueue只是一个消息储存单元,不会去处理消息,这时候Looper就出现了,Looper就会以无限循环的形式去查找是否有新消息,如果有的话就会处理 ,如果没有就会等待。 Looper中有一个重要的而有特殊的概念那就是ThreadLocal。
ThreadLocal是什么呢?
它并不是线程,它的作用是可以在每个线程中储存数据,Handler是如何获取当前的Looper呢?这也需要ThreadLocal,ThreadLocal不仅可以在每个线程互不干扰的情况下储存数据,还可以获取每个线程的Looper。
这里需要注意一个点就是线程默认可是没有Looper的,如果使用Handler就必须为线程创建Looper。
我们经常提到的主线程也叫UI线程,他就是Activity Thread,ActivityThread被创建时就会初始化Looper,这也是主线程默认可以使用Handler的原因。下面就是Handler的工作过程图
Handler工作过程
Message Queue的工作原理
它的作用主要是插入和读取。读取的操作会伴随着删除功能。插入方法enqueueMessage,读取方法next,next方法没取出一条消息并将其从队列中移除。
Looper的工作原理
Looper在Android中扮演着消息循环的角色,具体来说就是不停的查看消息队列中是否有新的消息,如果有新消息就会被处理,否则会被阻塞 首先我们先看看它的构造方法
Looper构造方法
它的构造方法会创建一个Message Queue,然后再把当前的线程对象保存起来。我们知道Handler的工作是需要Looper,没有Looper的线程就会报错,那么如何为一个线程创建Looper呢?很简单,就是调用Looper.prepare()方法来创建一个Looper,接着通过:Looper.loop()来开启消息循环的如下图所示
Looper除了prepare方法外,还有prepareMainLooper方法,这个方法主要给主线程(ActivityThread)创建Looper使用的,其本质还是通过prepare方法实现的,这个Looper提供了getMain Looper方法,通过它可以在任何地方获取到主线程的Looper,此外Looper也是可以退出的,通过quit和quitSafely来退出Looper,quit是直接退出,而quitSafely是做标记等到所有的消息处理完后才安全退出。如果退出Looper 线程就会终止,所以不建议推出。
Looper中最重要的方法就是loop方法,只有调用了消息系统才会起作用。
其实很好理解,loop方法是一个死循环,唯一跳出循环的方式是MessageQueue的next方法返回了null,怎么返回null呢?当Looper的quit方法被调用时Looper就会调用quit方法或者quitSafely来退出消息队列,这是就会返回null。如果得到新的消息就会通过msg.target.dispatchMessage(msg)方法处理消息,msg.target是发送消息的Handler对象,这样Handler发送消息就交给了dispatchMessage方法处理,而dispatchMessage方法是在创建Handler时所用的Looper中执行,所以就把逻辑代码切换到指定线程中执行了。
Handler的工作原理
Handler的工作主要是发送消息和接收过程,通过post和send方法来实现发送消息。
Handler发送消息只是向消息队列中插入了一条消息,Message Queue的next方法返回给Looper,Looper收到消息处理再交给Handler处理,也就是dispatchMessage方法
首先检查Message的callback是否为null,如果不为null就通过handleCallback来处理,其实Message的callback是一个Runnable对象,实际上也是Handlerpost方法传递的Runnable参数。
然后检查吗Callback是否为null,不为null就调用handleMessage方法来处理。Callback代码如下
通过Callback也可创建Handler对象:Handler handler = new Handler(callback)。
下图是Handler的流程图
Handler消息处理流程图