Android的消息机制只要是指Handler的运行机制,Handler的运行需要底层的MessageQueue和Looper的支撑。
Handler是Android消息机制的上层接口,这使得开发过程只需要和Handler交互即可。由于Android开发的限制,不能再子线程中访问UI控件,否则会触发程序异常(由ViewRootImp 的checkThread方法完成,throw CalledFromWrongThreadEcxeption),这个时候通过Handler就可以将更新UI的操作切换到主线程执行。因此,本质上来说,Handler并不是专门用于更新UI的,它只是常被开发者用来更新UI。
MessageQueue即消息队列,但它内部存储结构并不是真正的队列,而是采用单链表的数据结构来存储消息列表,提供对Message插入和删除的工作。
由于MessageQueue只是一个消息的存储单元,不能去处理消息,Looper就填补了这个功能,Looper会以无限循环的形式去查找是否有新消息,如果有就处理,没有就继续循环等待。Looper中还有一个特殊的概念,那就是ThreadLocal,ThreadLocal并不是线程,它的作用是可以在每个线程中存储数据。Handler创建的时候会采用当前线程的Looper来构造消息循环系统,ThreadLocal可以在不同的线程中互不干扰的存储并提供数据(不同线程中访问同一个ThreadLocal的set和get方法,它们对ThreadLocal所做的读/写操作仅限于各自线程的内部,这就是为什么ThreadLocal可以在多个线程中互不干扰得存储并提供数据),通过ThreadLoacl可以轻松获取每个线程的Looper。需要注意的是,线程默认是没有Looper的,如果需要使用Handler必须为线程创建Looper。(主线程中默认可以使用Handler的原因就是ActivityThread被创建时就会初始化Looper,具体的可以查看ActivityThread源码)。
Handler的主要作用是将一个任务切换到某个指定的线程中去执行,系统之所以提供Handler,主要原因就是为了解决在子线程中无法访问UI的矛盾。系统为什么不允许在子线程中访问UI呢?这是因为Android的UI控件不是线程安全的,如果在多线程中并发访问可能会导致UI控件处于不可预期的状态,那为什么系统不对UI控件的访问加上锁机制呢?缺点有两个:首先加锁机制会让UI访问的逻辑变得复杂;其次锁机制会降低UI访问的效率,因为锁机制会阻塞某些线程的执行。鉴于这两个缺点,最简单高效的方法就是采用单线程模型来处理UI操作,对于开发者来说也不是很麻烦,只需要通过Handler切换一下UI访问的执行线程即可
。
151

被折叠的 条评论
为什么被折叠?



