Android开发艺术探索学习笔记(十)
第十章 Android的消息机制
面试中经常会被问到的一个问题:handler是如何在子线程和主线程中进行消息的传递的,这个问题通过了解Android的消息机制可以得到一个准确的答案。
Android的消息机制主要就是指Handler的运行机制,Handler的运行需要底层的MessageQueue和Looper的支撑。需要理解两个概念:
MessageQueue:消息队列,通过单链表的数据结构来存储一组消息,以队列的形式对外提供插入和删除的工作。
Looper:消息循环,以无限循环的方式查找MessageQueue是否有新消息,有的话就处理消息,否则一直等待。
如果需要使用Handler就必须为Handler所在的线程创建Looper,主线程在创建的时候会自动初始化Looper,而子线程默认是没有Looper的,这就是在主线程默认可以使用Handler而子线程中默认不能使用Handler的原因。
Android系统之所以提供Handler,主要就是为了解决在子线程中无法访问UI的矛盾。之所以不允许在子线程中访问UI,主要是考虑到控件不是线程安全的,因为多个线程访问控件可能会导致UI控件处于不可预期的状态。
Handler,MessageQueue,Looper的工作工程如下图所示:
首先Handler通过post方法将一个Runnable或者send方法将一个消息投递到handler内部的Looper中,其实post方法最后也是通过send方法来完成的,所以以send方法为例,当send方法被调用后,它会调用MessageQueue中的enqueueMessage方法将这个消息放入MessageQueue中,此时looper发现MessageQueue中存在新消息,会开始处理这个消息,最终Handler中的handleMessage方法就会被调用,因为Looper是运行在创建Handler所在的线程中,这样一来就完成了消息在子线程和主线程中的传递。
MessageQueue主要包含两个操作,插入(enqueueMessage)和读取(next),读取本身会伴随这删除操作。enqueueMessage方法的作用是往消息队列中插入一条消息,next方法的作用是从消息队列中取出一条消息并将其从消息队列中移除。
Looper的主要作用就是不断的从MessageQueue查看是否有新消息,如果没有就一直阻塞在那里。
子线程中如果需要使用Handler那就必须先为子线程创建一个Looper,通过Looper.preper()可以为当前线程创建一个 Looper,然后通过Looper.loop()来开启消息循环,当使用完毕后需要调用Looper.quit()来终止消息循环,否则由于 Looper内部是一个死循环导致子线程会一直处于等待的状态,也就是线程不能结束。