可能是出于性能的考虑,Android的UI操作是非线程安全的。

也就是说,如果你在一个新开的线程中直接操作UI是会引发异常的。

但是,Android又规定,不要去阻塞UI线程!否则,轻者引起程序卡顿,重者直接引发臭名昭著的“ANR”异常。

为了解决这一种矛盾,Android引入了Handler来解决这个问题。

Handler有两种常见的用法:

第一种是“发送信息”,我们可以将我们要改变的参数通过Message发送给指定的Handler,然后在Handler中的handleMessage方法中进行处理。

另一种是将一个runnable对象“post”给Handler对象去执行。

实际上,这两种方法是没有太本质的区别的。

接下来从源代码的角度来看Handler的整个运行机制。

首先先来看看Message对象:

message中有几个比较重要的成员变量

what // 一个用来表示这个信息的类型

arg1 // 参数1

arg2 // 参数2

object // 可以携带任何一个对象

还有这一个:

这个东东就是用来传递Runnable对象的。

接下来看Handler的sendMessage方法:

可以看到,它实际上是调用另一个发送的方法,我们跟进去:

靠,原来这几个方法是一回事来的,继续看:

终于不一样了~~~,这里多了一个MessageQueue对象,神马东西?从名字上看应该是“信息队列”的意思。也就是说,实际上,我们发送给Handler的信息并不是直接交给Handler去处理,而是Handler会把Message先放入一个MessageQueue中。MessageQueue就是一个数据结构,以队列的形式管理Message。那么,谁又把Message从Message从MessageQueue中拿出来呢?

这就需要另一个对象Looper了。

Looper的构造方法很有意思:

那也就是说我们是无法直接创建Looper对象的,经验告诉我们,这种情况下,一般不是单例就是工厂。实际上是这个:

这个方法保证了一个线程中只有一个Looper对象,否则会出现异常。

实际上,Looper中有一个loop方法:

上面是我把无关代码去掉后的loop方法,这个方法中looper对象一直去调用MessageQueue的next()方法,也就是不断地从消息队列中取出消息,然后重点来了:

嗯,这一步就是把消息交给对应的Handler去处理。

那么post一个Runnable对象又是怎么做到的呢?

这方法看起来相当的亲切啊!猜应该也可以猜到了getPostMessage方法是怎么实现了吧:

猜对没有?

所以本质上都是通过发信息来实现的。

看看dispatchMessage是怎么做的吧:

接下来就好说了,如果callback不是null,那就是让它去run咯!如果是普通消息, 那就是靠我们自己写的handleMessage去处理了。

至此,Handler的运行机制就是这些了。很喜欢张龙老师的一句话:源代码下,了无秘密。

总结一下:

Message:这个对象携带着我们想做的信息。

MessageQueue:以队列的形式管理Message对象。

Looper:每个线程只有一个Looper对象,它负责管理MessageQueue,会不断地从中取出Message对象,交给相应的Handler去处理。

Handler:它把Message发送给Looper维护的MessageQueue,并负责处理Looper传递过来的Message对象。

by yjiyjige 2013.06.19

Android学习笔记——从源码看Handler的处理机制的更多相关文章

  1. Hadoop学习笔记(9) ——源码初窥

    Hadoop学习笔记(9) ——源码初窥 之前我们把Hadoop算是入了门,下载的源码,写了HelloWorld,简要分析了其编程要点,然后也编了个较复杂的示例.接下来其实就有两条路可走了,一条是继续 ...

  2. [转]OpenTK学习笔记(1)-源码、官网地址

    OpenTK源码下载地址:https://github.com/opentk/opentk OpenTK使用Nuget安装命令:OpenTK:Install-Package OpenTK -Versi ...

  3. 从Chrome源码看浏览器的事件机制

    .aligncenter { clear: both; display: block; margin-left: auto; margin-right: auto } .crayon-line spa ...

  4. Nginx学习笔记4 源码分析

    Nginx学习笔记(四) 源码分析 源码分析 在茫茫的源码中,看到了几个好像挺熟悉的名字(socket/UDP/shmem).那就来看看这个文件吧!从简单的开始~~~ src/os/unix/Ngx_ ...

  5. Linux简易APR内存池学习笔记(带源码和实例)

    先给个内存池的实现代码,里面带有个应用小例子和画的流程图,方便了解运行原理,代码 GCC 编译可用.可以自己上网下APR源码,参考代码下载链接: http://pan.baidu.com/s/1hq6 ...

  6. Vue2.x源码学习笔记-Vue源码调试

    如果我们不用单文件组件开发,一般直接<script src="dist/vue.js">引入开发版vue.js这种情况下debug也是很方便的,只不过vue.js文件代 ...

  7. Android学习笔记(十四) Handler理论补充

    一.如何下载Android源码 在SDK Manager中选中Sources for Android SDK. 二.ThreadLocal初步介绍 1)执行ThreadLocal对象(static f ...

  8. linux学习笔记-lrmi源码包的编译安装方法

    我的邮箱地址:zytrenren@163.com欢迎大家交流学习纠错! 官方的lrmi包没有人更新了,如果碰到需要这个编译安装这个包,可以参考我的解决思路,如下: https://pkgs.org/这 ...

  9. MarkDown语法 学习笔记 效果源码对照

    MarkDown基本语法学习笔记 Markdown是一种可以使用普通文本编辑器编写的标记语言,通过简单的标记语法,它可以使普通文本内容具有一定的格式. 下面将对Markdown的基本使用做一个介绍 目 ...

随机推荐

  1. sql注入语句整理

    1.判断有无注入点; and 1=1 and 1=2 2.猜表一般的表的名称无非是admin adminuser user pass password 等..and 0<>(select ...

  2. Nuxeo 认证绕过和RCE漏洞分析(CVE-2018-16341)

    简介 Nuxeo Platform是一款跨平台开源的企业级内容管理系统(CMS).nuxeo-jsf-ui组件处理facelet模板不当,当访问的facelet模板不存在时,相关的文件名会输出到错误页 ...

  3. 实验作业:使gdb跟踪分析一个系统调用内核函数

    实验作业:使gdb跟踪分析一个系统调用内核函数(我使用的是getuid) 20135313吴子怡.北京电子科技学院 [第一部分] 根据视频演示的步骤,先做第一部分,步骤如下 ①更新menu代码到最新版 ...

  4. spring @component的作用

    该文转载自:http://tomfish88.iteye.com/blog/1497557 1.@controller 控制器(注入服务) 2.@service 服务(注入dao) 3.@reposi ...

  5. 从零开始学Kotlin-基础语法(1)

    从零开始学Kotlin基础篇系列文章 注释 //单行注释 /* 多行注释 */ /** * 多行注释 */ 定义变量/常量 变量定义:var 关键字 var <标识符> : <类型& ...

  6. delphi Timage 加上滚动条方法

    elphi Timage 加上滚动条方法 1:将  Timage 放入 TScrollBox内,即   [1]设image1.parent:= ScrollBox1;   [2]在Object Ins ...

  7. EntityFramework 数据校验异常处理

    public void Insert(PageHost entity) { try { db.pagehost.Add(entity); db.SaveChanges(); } catch (DbEn ...

  8. shell之三大文本处理工具grep、sed及awk

    grep.sed和awk都是文本处理工具,虽然都是文本处理工具单却都有各自的优缺点,一种文本处理命令是不能被另一个完全替换的,否则也不会出现三个文本处理命令了.只不过,相比较而言,sed和awk功能更 ...

  9. MT【77】函数的定义理解

    答案:D.比如C 中令$x^2+1=2,x=-1,1,$ 得$f(2)=0,2$与定义矛盾,A,B同理排除. D中注意到$x^2-2x$与$|x-1|$对称轴都是$x=1$. 评:函数的定义,首先是两 ...

  10. 【题解】 [HNOI2015]菜肴制作 (拓扑排序)

    题目描述 知名美食家小 A被邀请至ATM 大酒店,为其品评菜肴. ATM 酒店为小 A 准备了 N 道菜肴,酒店按照为菜肴预估的质量从高到低给予1到N的顺序编号,预估质量最高的菜肴编号为1. 由于菜肴 ...