Android学习笔记——从源码看Handler的处理机制
可能是出于性能的考虑,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的处理机制的更多相关文章
- Hadoop学习笔记(9) ——源码初窥
Hadoop学习笔记(9) ——源码初窥 之前我们把Hadoop算是入了门,下载的源码,写了HelloWorld,简要分析了其编程要点,然后也编了个较复杂的示例.接下来其实就有两条路可走了,一条是继续 ...
- [转]OpenTK学习笔记(1)-源码、官网地址
OpenTK源码下载地址:https://github.com/opentk/opentk OpenTK使用Nuget安装命令:OpenTK:Install-Package OpenTK -Versi ...
- 从Chrome源码看浏览器的事件机制
.aligncenter { clear: both; display: block; margin-left: auto; margin-right: auto } .crayon-line spa ...
- Nginx学习笔记4 源码分析
Nginx学习笔记(四) 源码分析 源码分析 在茫茫的源码中,看到了几个好像挺熟悉的名字(socket/UDP/shmem).那就来看看这个文件吧!从简单的开始~~~ src/os/unix/Ngx_ ...
- Linux简易APR内存池学习笔记(带源码和实例)
先给个内存池的实现代码,里面带有个应用小例子和画的流程图,方便了解运行原理,代码 GCC 编译可用.可以自己上网下APR源码,参考代码下载链接: http://pan.baidu.com/s/1hq6 ...
- Vue2.x源码学习笔记-Vue源码调试
如果我们不用单文件组件开发,一般直接<script src="dist/vue.js">引入开发版vue.js这种情况下debug也是很方便的,只不过vue.js文件代 ...
- Android学习笔记(十四) Handler理论补充
一.如何下载Android源码 在SDK Manager中选中Sources for Android SDK. 二.ThreadLocal初步介绍 1)执行ThreadLocal对象(static f ...
- linux学习笔记-lrmi源码包的编译安装方法
我的邮箱地址:zytrenren@163.com欢迎大家交流学习纠错! 官方的lrmi包没有人更新了,如果碰到需要这个编译安装这个包,可以参考我的解决思路,如下: https://pkgs.org/这 ...
- MarkDown语法 学习笔记 效果源码对照
MarkDown基本语法学习笔记 Markdown是一种可以使用普通文本编辑器编写的标记语言,通过简单的标记语法,它可以使普通文本内容具有一定的格式. 下面将对Markdown的基本使用做一个介绍 目 ...
随机推荐
- M1阶段事后总结
设想和目标 1. 我们的软件要解决什么问题?是否定义得很清楚?是否对典型用户和典型场景有清晰的描述?我们组要爬取网上的内容供下一组使用,定义的不太清楚,因为用户只有下一个团队所以没有进行详细的需求分析 ...
- 2018软工实践—Beta冲刺(7)
队名 火箭少男100 组长博客 林燊大哥 作业博客 Beta 冲鸭鸭鸭! 成员冲刺阶段情况 林燊(组长) 过去两天完成了哪些任务 协调组内工作 整体软件测试 展示GitHub当日代码/文档签入记录(组 ...
- Leetcode题库——48.旋转图像
@author: ZZQ @software: PyCharm @file: rotate.py @time: 2018/11/16 15:41 要求:给定一个 n × n 的二维矩阵表示一个图像.将 ...
- 数学口袋精灵app(小学生四则运算app)开发需求
数学口袋精灵APP,摒除了传统乏味无趣学习数学四则运算的模式,采用游戏的形式,让小朋友在游戏中学习,培养了小朋友对数学的兴趣,让小朋友在游戏中运算能力得到充分提升.快乐学习,成长没烦恼! 项目名字:“ ...
- 作业6小学生四则运算测试APP的NABCD模型
小学生四则运算测试NABCD模型 组员:李新,朱浩龙,叶煜稳,陈俊金,林德麟 (1) N (Need 需求) 需求分析: 四则运算是小学生学习数学的核心和基础,必须经过大量的练习才能熟练掌握,但是一 ...
- Daily Scrum - 11/16
时间:午饭 今天小组例会主要是汇报了各自的进度.任烁那边主要为工程添加了单词的类(包含各个参数等成员变量),方便以后实现算法:拜重阳实现了一个简易的“点进-点出”UI,可谓迈出了艰难的第一步:章玮和罗 ...
- Alpha 冲刺报告模板
Alpha 冲刺报告模板 Deadline: 十分钟左右站立会议,控制好时间,不要在此会议上讨论细节问题. 每组一份博客,组内共享,每人都需提交. 模板 队名:xxx 组员1(组长) 今天完成了哪些任 ...
- Window环境下RabbitMQ的安装和配置教程
一.安装 首先,RabbitMQ基于Erlang语言环境,所以需要先安装Erlang. Erlang下载地址:http://www.erlang.org/downloads 按照安装程序默认安装完成就 ...
- final 140字评论I
1.约跑app:优化了最终界面,设备原因画质不是很清晰,如果能加以改进,能有较多的客户群,适合人群不限于青少年和成年人. 2.礼物挑选:虽然界面不是很清晰,但是整体设计看起来还算舒服,最后阶段又新增了 ...
- vue-resource和axios区别
vue-resource Vue.js是数据驱动的,这使得我们并不需要直接操作DOM,如果我们不需要使用jQuery的DOM选择器,就没有必要引入jQuery.vue-resource是Vue.js的 ...