朝花夕拾回过头来做整理:Handler
Posted andy-songwei
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了朝花夕拾回过头来做整理:Handler相关的知识,希望对你有一定的参考价值。
android中子线程和UI线程(即主线程),就想古时候的痴男和怨女。某天,一痴汉看上了一妹子,一见钟情,想要表达爱意和提亲。可是,那个时代,即使再心急火燎的,也不能冒冒失失直接去找妹子求婚啊。怎么办呢?痴汉顺理成章想到了媒婆——Handler!稍有一点Android开发基础的朋友都知道“主线程不做耗时操作,子线程不更新UI ”。可是当子线程完成耗时操作,需要更新UI,要怎么办呢?Handler作为一名经验老到的媒婆,在痴汉(子线程)和妹子(UI线程)之间扮演了总要的信使角色。
1. 痴汉委托媒婆送情书。
① sendMessage(Message msg)源码截图
② sendEmptyMessage(int what)源码截图
③ post(Runnable r) 源码截图
④ postDelayed(Runnable r, long delayMillis)源码截图
看,多么熟悉的面孔!!!没错,sendMessage(...),sendEmptyMessage(...), post(...), postDelay(...),平时使用最广泛的四个方法,媒婆Handler主要就是靠的这四招,替子线程向UI线程递信(发送Message)的。从上图中左上角我们可以直观地看到,这四个方法都直接或间接递地在调用sendMessageDelay(...)方法。殊途同归,Handler无论使用何种方法,其宗旨都是在想办法传递信息。无疑,Handler这个媒婆很聪明,会根据不同的场景选择使用其中的一种合适的方法。
2.媒婆把情书存入信箱。
sendMessageDelay(...)层层往下走,会调用enqueue(...)方法。该方法会触发MessageQueue调用自己的enqueueMessage(...)方法。
MessageQueue中enqueueMessage(...)方法的关键代码如下:
MessageQueue,就像妹子的信箱,媒婆(Handler)送来的情书(Message)就被存储这个里面。它的学名叫做消息队列,从源码总可以看到,它采用链表的形式,无限循环将消息加入其中。
3. 妹子派丫鬟取情书。
情书总是不期而至,媒婆把情书放入信箱,却没有通知妹子,妹子又如何知道意中人有信件送达呢?原来,妹子是大家闺秀,专门有丫鬟伺候她,时时刻刻检查着信箱。这个丫鬟就叫Looper,扮演着重要的角色。
Looper中有个loop( )方法,正如以下代码所示,本质上是调用MessageQueue.next( )方法。这个方法可以对应MessageQueue.enqueueMessage(...)方法,一个无限循环存入Message,另一个就无限循环取出Message。就是Looper这个勤劳的丫鬟在不停查看信箱,有情书到了,就取出来交给妹子。如下代码显示了Looper从消息队列中取消息的关键代码,可以看到这是一个无限循环的过程。这里,要着重注意第14行, msg.target在前面的enqueueMessage(...)方法中有提到,"msg.target = this", 说明它就是Handler的一个实例,对应UI线程中new的Handler实例,它调用了dispatchMessage(msg),该方法的作用就是安排处理Message,后面(妹子读情书)中会详细讲到。
1 public static void loop() { 2 final Looper me = myLooper(); 3 if (me == null) { 4 throw new RuntimeException("No Looper; Looper.prepare() wasn‘t called on this thread."); 5 } 6 final MessageQueue queue = me.mQueue; 7 ...for (;;) { 8 Message msg = queue.next(); // might block 9 if (msg == null) { 10 // No message indicates that the message queue is quitting. 11 return; 12 } 13 ...try { 14 msg.target.dispatchMessage(msg); 15 ... 16 } finally { 17 ... 18 } 19 ... 20 msg.recycleUnchecked(); 21 } 22 }
那么问题来了,Looper又是从哪里来的呢?难道是和孙猴子一样从石头中蹦出来的?Android程序本质上也是java程序。我们总是疑惑,为什么我们的app中怎么也找不到main( ) 入口?哈哈,其实仍然是有main( )入口函数的,在ActivityThread中:
1 public static void main(String[] args) {
2 ...
3 Looper.prepareMainLooper();
4 ...
5 Looper.loop();
6 ...
7 }
豁然开朗了吧,Looper的身世都在main(...)方法中!Looper.prepareMainLooper()作用是生成一个Looer实例,然后就Looper就调用了loop( )方法,开启了她作为丫鬟勤劳的一生。
只能说妹子的命是真好,有个好爹,她从出生开始,老爹就为她安排好了体贴的丫鬟,全心全意地为她服务着。
4.妹子读情书。
上一节 ”妹子派丫鬟取情书”中提到了该方法。此刻,情书已经到了妹子的手中, 妹子要开始享受地读情书了。
5.妹子的反应。
以上是关于朝花夕拾回过头来做整理:Handler的主要内容,如果未能解决你的问题,请参考以下文章