在Android中,Looper、MessageQueue和Hander是相互协作的三个组件,它们共同构成了Android的消息处理机制。其实个人认为和餐厅运营模式很相似。
存在的意义
在Android中,如果在主线程中进行耗时操作,会导致ANR(无响应弹窗),所以耗时操作一般给子线程进行处理。
通过学习了解到,在Android中访问UI只能在主线程中进行。如果在子线程进行对UI的操作会导致异常。
那么问题又来了,为什么不能在子线程中对UI进行操作呢?
通过学习得知,是因为Android的UI控件不是线程安全的。
问题又来了,什么是线程安全呢?
线程安全
线程安全也就是内存安全,因为在每个进程间都有一个公共区域叫做堆空间(内存),在该进程中所有的线程都能访问到这个空间,因此如果不加以限制,那么这个空间就有可能被其他线程修改导致不可预期的问题。
那么问题又又来了,那加限制不就行了(加锁)?
因为这个action使得UI的访问逻辑更加复杂,进而拖慢效率。想一想如果你的手机点击一个应用半天才进去,是不是感觉很难受。
因此Android的消息机制诞生了。
三组件
MessageQueue(消息队列——订单)
消息队列是以单链表来进行数据存储。在消息机制中,它负责按时间顺序存储Handler发送过来的消息,然后等待Looper来按照先进先出的顺序来取走消息。
(订单按照下单的时间戳进行编号,先订先吃。经理根据订单来给服务员下达送菜命令)
Looper(打环的人——餐厅经理)
Looper是一个消息循环器,它负责不断从消息队列中取走消息再发给对应的Handler进行处理。
(经理会不断查看是否有新的订单出现,如果有新的订单出现,就安排服务员按照订单送菜)
知识:
每个线程只有一个looper;
一个looper又维护着一个消息队列;
通过Looper.prepare()来初始化Looper;
通过Looper.loop()让线程进入消息循环状态。
Handler(处理者——服务员)
Handler用于同一个进程中线程间的通信。
handler发消息给MessageQueue也从Looper手中收消息。
(服务员既要去询问顾客吃啥并形成订单,也要按照经理的指挥上菜)
那么现在假设一个情景,我需要在我的Android应用主页显示一个圆形按钮,但是假设显示这个圆形按钮的条件是耗时的。那么如何保证在主页能正常显示出圆形按钮呢。
我们以图像来描述一下流程。
情景描述
按照餐厅流程来描述,顾客在餐厅点菜,但无奈他有选择困难症(耗时),几番犹豫点了汉堡(圆形按钮),handler(服务员)将这个订单按照时间进行排队(消息队列,先订先吃),Looper(餐厅经理)按照订单顺序将餐分给对应的服务员(handler),值得注意的是,经理会时不时的来查看有没有新订单(轮询),服务员按照经理的指令将对应的餐给对应的顾客,最后汉堡上桌了(形成圆形按钮)