简单明了说Handler和Looper

作者: 工程师milter | 来源:发表于2016-06-26 20:55 被阅读1597次
简单明了说Handler和Looper

本文产生原因是由于我始终相信三点,即:

  • 任何技术都是为了解决实际存在的问题而产生的。
  • 任何技术的基本原理都是简单明了的。
  • 搞清楚一项技术要解决的问题,理解它的基本原理是学习一项技术最好最快最省力的方法。

一、google为什么设计这套机制

主要是为了解决在非UI线程中更新UI组件比较麻烦的问题。

二、google如何实现这套机制

UI线程中有一个线程专属的Looper对象,它负责安排所有准备在UI线程上执行的代码。这里有两点技术:实现UI线程专属的Looper对象用到了java的ThreadLocal技术,想深究请直接看ThreadLocal源码,不难,真心不难,当然不看也行,只要知道有这么回事也够,需要时再看。Looper对象通过消息机制接受系统或者应用的其他线程提交的准备在UI线程上执行的代码。提交方式是:以该Looper对象为参数创建一个Handler对象,也可以在UI线程中无参数构建一个Handler对象,此时的Handler对象直接就与UI线程的Looper对象绑定。Handler对象负责向Looper对象提交代码。最直接的提交方法是调用Handler对象的post方法,该方法的参数是一个Runnable对象,代表了要在UI线程上执行的代码。这样的方法简单但是没法传递数据给要执行的代码,因为构造Runnable对象是没有参数的。为此,google提供了另一种提交代码的方法,就是让Handler对象发送一个消息给Looper对象,这个消息中可以包含一定的数据(消息的what域和obj域就是用来包含数据的),要执行的代码就是Handler中的handleMessage方法,该方法会收到发送给Looper的消息,进而可以从中取出数据再执行代码。

以上为原理。

三、一些可以帮助理解原理的细节

因为Looper是给UI线程安排代码的,所以一个UI线程只能有一个Looper对象,否则多个Looper对象都要在UI线程上安排代码,解决冲突就是个大难题。因为Looper对象是线程专属的,所以一个Looper也只能对应一个UI线程。二者是一对一的关系。但是一个Looper对象可以有多个Handler对象向它提交代码,这并不会引起代码冲突。因为Looper对象会线性安排在UI线程上待执行的代码,它通过一个队列管理各个Handler对象提交的代码。Looper对象安排执行代码靠的是它的loop方法。

四、具体使用方法

将一个与UI线程上Looper对象关联的Handler对象传给其他线程,其他线程通过这个对象向UI线程上提交代码。

五、该机制的一般性扩展

实际上,可以为任意一个线程创建一个唯一的Looper对象,这是通过Looper类的静态方法prepare实现的,然后可以用这个Looper对象创建一个或多个Handler对象,然后就可以用这些Handler对象向该线程提交执行代码了,google提供了一个HandlerThread类,就是一个已经实现好了Looper对象的Thread,方便你的使用。

如果觉得本文对你有所帮助,希望不要吝惜你的大拇指,给点个赞。

相关文章

网友评论

  • winky612:楼主多多写分享哈。我看了无数讲handler的文章,真的只有这篇有种瞬间开窍的感觉。赞一个👍
  • EDG不是本地g:tmd~~~ :sunglasses: 我就服你~~~滑稽脸~~~
    工程师milter: @yxdd 好吧,我服了你了!
    EDG不是本地g:@milter :blush: hhh 不得 我就服你
    工程师milter: @yxdd 我们都要服google
  • 看秋叶一片片飘落:深入浅出,很好!
  • zxwei09:我对Looper、handler、MessageQueue,Msg的理解是Looper像是工头儿,指派工人工作的,而Handler就是工人,MessageQueue是一个循环的工作传送装置,Message是其中的一种工作,当有工作(Message)的时候,工头儿(Looper)安排工作,叫工人(Handler)去工作队列(MessageQueue)里去取个工作(Message)回来,以此来进行交替。是否有不妥之处,还望指正 :smile:
    工程师milter:@zxwei09 awesome good idea
  • q2nAmor:二 google如何实现这套机制中,你这样说“为此,google提供了另一种提交代码的方法,就是让Handler对象发送一个消息给Looper对象".......。消息不应该是发送到消息队列吗?looper的作用是从中拿取消息,而不是looper对象接收消息。
    工程师milter: @流苏没魅力 队列归属于Looper管理,二者是一体的,可分不可离,所以在写时就简化了下,主要是为了方便理解。
  • Android阿杜:Android多线程消息机制涉及到的Thread,Handler,Looper,Message,MessageQueue等知识远不止这点,更有许多队巨坑需要我们深入了解,可以参考卑文:http://blog.csdn.net/fesdgasdgasdg/article/details/52081773
    工程师milter:@写代码的阿杜 也就是looper内部实现原理
    工程师milter: @写代码的阿杜 希望能看到更多细节的文章
    工程师milter: @写代码的阿杜 我主要是想简单明了说清楚这个知识点的来龙去脉,不打算深究细节,当然,深入细节就必须写明白不同线程到底是怎么通信的。
  • 91ff408ee169:写的挺好的哦
    工程师milter: @ElegantDancer 谢谢,这个知识点挺重要,但却不难。
  • 捡淑:马克
  • Vivi成长吧:“一个Looper也只能对应一个UI线程”,后面又写到“实际上,可以为任意一个线程创建一个唯一的Looper对象”,那么这里的任意一个线程可以是子线程吧? 与之前说的UI线程不是矛盾了么
    工程师milter: @拼命七娘 这是步步深入的写法,前面讲时,还仅在UI线程中讨论,后面扩展了讨论范围,所以,我加了句“实际上”
  • fc681483162b:前面的那三句话不错
    工程师milter:@许你壹世静好岁月 学技术后,这是最深刻的感悟了

本文标题:简单明了说Handler和Looper

本文链接:https://www.haomeiwen.com/subject/osczdttx.html