Android的消息机制主要指Handler的运行机制,Handler的运行需要底层的MessageQueue和Looper的支撑。MessageQueue就是消息队列,内部存储了一组消息,以队列的形式对外提供插入和删除的工作,它的内部存储结构是采用单链表的数据结构来存储消息队列。Looper是消息循环,它会无限循环查找是否有新消息,如果有的话就去处理消息,没有就一直处于阻塞状态等待新消息的到来。
Handler的主要作用是将一个任务切换到某个指定的线程中去执行。那为什么要切换到某个指定的线程呢?因为在主线程即UI线程中操作耗时的任务,容易引发ANR,另外Android中规定访问UI只能在主线程进行。所以像访问网络这种耗时的操作就需要在子线程中进行,访问的结果然后通过Handler再回到主线程进行相应的操作,如果我们需要将访问网络的结果显示在UI上的话。系统不允许在子线程中访问UI的原因是因为Android的UI控件是线程不安全的,如果在多线程中并发访问可能会导致UI控件处于不可预期的状态。
Handler的工作原理概述:Handler创建完毕后,其内部的Looper以及MessageQueue就可以和Handler一起协同工作了,然后通过Handler的post方法将一个Runnable投递到Handler内部的Looper中去处理,或者通过Handler的send方法发送一个消息,这个消息同样会在Looper中去处理。当Handler的send方法被调用,它会调用MessageQueue的enqueueMessage方法将这个消息放入消息队列中,然后Looper发现有新消息来到时,就会处理这个消息,最终Handler的handlemessage方法会被调用。
消息队列MessageQueue中两个主要操作,消息的插入和读取分别对应enqueueMessage()方法和next()方法。其中enqueueMessage()方法完成消息的插入,主要操作就是单链表的插入工作;next()完成消息的读取,它是一个无限循环,等待消息的到来,如果消息队列中没有消息,next()方法就一直阻塞,当有新消息到来时,next()方法就会返回这条消息并将其从单链表中移除。
消息循环Looper,它会不停地从MessageQueue中查看是否有新消息,如果有就处理,否则就一直阻塞在那里。Looper的loop()方法,是一个死循环,唯一跳出循环的方式是MessageQueue的next()方法返回为null。当Looper的quit()方法被调用,Looper就会调用MessageQueue的quit()或者quitSafely()方法来通知消息队列退出,当消息队列被标为退出状态时,它的next()方法就会返回为null。也就是Looper必须退出,否则loop()方法就会无限循环下去。loop()方法会调用MessageQueue的next()的方法来获取消息,而next()是一个阻塞操作,当没有消息时,next()方法会一直阻塞在那里,这也导致loop()方法一直阻塞在那里。如果MessageQueue的next()方法返回了消息,Looper就会处理这条消息:msg.target.dispatchMessage(msg),其中msg.target就是发送消息的Handler对象,这样Handler发送的消息最终又交给了它的dispatchMessage()方法来处理了。但是Handler的dispatchMessage()方法是在创建Handler时所使用的Looper中执行的,这样就成功的将代码逻辑切换到指定的线程中去执行了。
Handler工作原理:
以下面的例子进行分析:因为需要进行网络访问获取图片资源,所以这一步就需要在子线程中进行,访问的结果又需要设置给主线程中的ImageView进行显示,所以需要将访问的结果通过Handler发送到Handler所在的主线程进行处理。
在子线程中进行网络访问,创建Message对象,将需要返回给UI线程的操作的数据通过Message对象的obj属性进行绑定,设置Message对象的what属性进行数据返回成功与否的判断标志,通过在UI线程中创建的Handler对象将消息发送出去。
Handler对象发送Message对象的过程中,sendMessage()方法会调用sendMessaageDelayed()方法,sendMessaageDelayed()会调用sendMessageAtTime()方法,sendMessageAtTime()方法会调用enqueueMessage()方法,enqueueMessage()会调用queue.enqueueMessage()方法,即会调用消息队列的插入消息方法,向消息队列插入这条消息。然后消息队列MessageQueue的next()方法就会将这条消息返回给Looper的loop()方法,将消息交给Handler处理。Handler的dispatchMessage()会被调用,进行消息处理,调用Handler的handleMessage()方法进行处理。
主线程中新建Handler对象并重写handleMessage()方法,对子线程中发送来的消息进行处理。