站在设计者的角度去思考和学习Handler机制

线程间的通信机制?为什么要进行线程间通信,同一进程间的多个线程不是共享内存资源吗,还需要进行通信吗?没错,确实需要这样的一个机制。比如,刚刚开始学习Android的时候,我就听别人说在主线程不能做耗时操作,会导致anr,那么,如果子线程的工作做完了并且需要将结果反馈给主线程让其更新UI,这个时候我们就迫切的需要这样的一套机制,来达到线程间通信的目的,也就是Android的Handler机制。

这里,先假设自己没有看过Handler机制的源码,如果让我们来设计这套机制,应该怎么做呢?这套机制该怎么来实现呢?利用面向对象的思想,首先想到的是得有个Message类来封装消息,其次消息得有人来处理,就好比快递包裹得有人来派送,所以得有个Handler类,来扮演处理Message的角色。有了Message和处理Message的Handler,这还不够,因为每个线程一定会接收到很多Message,而且你不确定什么时候会接收到Message,所以搞一个MessageQueue是非常有必要的。那么问题又来了,有了存放Message的MessageQueue,那谁来维护MessageQueue呢,这个角色需要一直"活着",只要线程还在就不允许它挂掉,因为我们不确定线程什么时候会收到消息,当MessageQueue该被处理的消息都已经处理完了,我们可以允许它小睡一会,但是死掉是绝对不可以的。这个辛劳的角色就是我们的Looper。

以上,我们先大致确定了几个重要角色:Message , Handler , MessageQueue , Looper。紧接着要去更具体的去实现它,假设现在有这样的场景,线程A要给线程B发送消息,那么第一步,线程A要把自己的“想法”封装到一个Message对象msg中,这个好说,那么接下来就像我们寄快递会把包裹交给了快递小哥一样,线程A将msg交给了Handler,这里值得我们特别注意,我们寄快递的时候总是特别小心,反复检查目的地的地址是否正确,接收方的电话是否填写正确,同样的,线程A也不能随意的将msg托付给一个“不靠谱”的Handler,所以我们的Handler必须要设置一个“可以确定线程B的属性”,那怎么谁可以用来确定msg是给了线程B呢,谁可以成为线程B的代言人呢?这个点是非常关键的,深思熟虑后,这个角色非辛劳的Looper莫属。如前面所说,Looper要永远活着,永远在“处理”或者“准备处理”MesaageQueue中的Message,这么“伟大且重要”的角色每个线程都是要有的,而且只能有一个,为什么,因为一个就够了哈。说回正题,现在线程A将msg将给了Handler,这个Handler封装了一个线程B的Looper对象,而我们的Looper维护着一个MessageQueue,最终msg进入MessageQueue,等待线程B的Looper来处理它。那么,按照一定的顺序,终于轮到来自线程A的msg了,怎么处理?谁来处理?其实Handler就可以处理,只要给msg封装一个Handler对象就可以,等到线程B的Looper从MessageQueue将msg取出来后,获取到msg封装的Handler,然后让Handler去处理。

至此,总体的一个框架已经有了。但是要去实现它,还有很多问题。

问题1:每个线程都要有且只有一个Looper去接收并且分发Message,换句话说也就是维护MessageQueue,那么怎么实现每个线程有属于自己私有的Looper,彼此隔离互不影响,这就涉及到“线程隔离”的问题。所以我认为ThreadLocal是Handler机制非常重要的一个点。

问题2:还是围绕Looper,Looper可以“睡着”但是绝不可以“死掉”,换句话说,MessageQueue中有可以被处理(或者换个词“分发”更为准确)时,它必须得活着并且去分发Message,当MessageQueue中没有可以被分发的消息时,它可以“睡着”,或者说是“休眠”。那么怎么保证它“长生不老”,“死不掉”呢?没错,那就是死循环,这看起来有点怪,让它死不掉而去死循环。说到这还不明白的话,可以试想,如果不是死循环,你的Looper总有循环结束的时候,那个时候你的线程可能并没有死掉,而别的线程给你发送消息,要跟你通信,怎么办?答案是没办法了,通信失败,因为“伟大”的Looper已经死掉了。想通了“死不掉”的问题,那怎么解决“睡得着”的问题,毕竟总有空闲的时候,在Looper维护的MessageQueue中在一些时候,没有可以被分发的Message,这种时候得让"Looper"“睡得着”,这块会调用jni,让线程休眠。(这块是我的猜想,可能不正确)。

问题3:看了源码后,会发现Message的类型有三种,普通Message,异步Message,屏障Message。这些Message的区别可以在MessageQueue取Message时体现出来,这算是一些细节问题,不展开讨论了。

问题4:一般我们在用Handler时,通常是以内部类的形式,但是如果没有定义为static的话,AS会提示可能会导致内存泄漏,可以从这个点学习下关于内存泄漏,垃圾回收机制,可达性分析等概念。具体就不展开讨论了。

简单总结下:其实Handler机制总体来说并不复杂,涉及的角色(类)并不多,逻辑也比较简单,重点我认为在于实现Looper的线程隔离,以及loop的休眠唤醒机制。当然,Handler机制也并不简单,里面有很多细节的地方值得我们取学习,比如获取和管理Message的方式(享元设计模式),比如休眠唤醒的机制,可以继续向下挖掘,学到更多的东西等等。

本文是站在一个“设计者”的角度去思考和学习Android线程间通信机制(Handler机制),并没有去对代码进行分析,而是去尝试理解其中的设计思路,宏观上去理清整套机制的脉络及流程。如有不对的地方,欢迎大家指正!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,123评论 6 490
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,031评论 2 384
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,723评论 0 345
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,357评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,412评论 5 384
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,760评论 1 289
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,904评论 3 405
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,672评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,118评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,456评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,599评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,264评论 4 328
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,857评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,731评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,956评论 1 264
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,286评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,465评论 2 348

推荐阅读更多精彩内容