Handler消息处理机制详解
之前一直只知道handler如何使用,不知道其中的工作原理,趁着新版本提测阶段比较空闲,及时做一个总结。
先看一下Google官方文档关于handler的解释:
A Handler allows you to send and process Message and Runnable objects associated with a thread's MessageQueue. Each Handler instance is associated with a single thread and that thread's message queue. When you create a new Handler, it is bound to the thread / message queue of the thread that is creating it -- from that point on, it will deliver messages and runnables to that message queue and execute them as they come out of the message queue.
There are two main uses for a Handler: (1) to schedule messages and runnables to be executed as some point in the future; and (2) to enqueue an action to be performed on a different thread than your own.
巴拉巴拉一大堆,还好没有什么生僻词大概还能看懂个意思,大概意思就是:handler类允许你发送消息和处理线程消息队列中的消息及runnable对象。handler实例都是与一个线程和该线程的消息队列一起使用,一旦创建了一个新的handler实例,系统就把该实例与一个线程和该线程的消息队列捆绑起来,这将可以发送消息和runnable对象给该消息队列,并在消息队列出口处处理它们。
handler类有两种主要用途:1、按照时间计划,在未来某时刻,对处理一个消息或执行某个runnable实例。 2、把一个对另外线程对象的操作请求放入消息队列中,从而避免线程间冲突。
第一个就是执行一个定时任务(可以立刻执行,比如子线程刷新ui),第二个就是异步消息处理机制。
将通俗一点就是1.更新ui 2.实现消息的异步处理
Part1.更新ui:

有的时候在我们需要执行一些耗时的操作,然后执行完了给一个反馈,如上代码开启了一个子线程去下载lol,然后下载完成后提示下载完成,当程序执行到L:64的是后程序崩溃了,报错原因是只有在主线程才能修改视图,L:65-L:70就是一种handler的典型用法,在子线程post出一个runnable对象,还有其他的方式,比如通过sendMsessage(其实post的内部也是实现sendmessage,ps:message的获取方式Android推荐Message.obtain而不是直接new),L:77和L:79是一种消息不带数据的和一种消息带数据的传递,看一下最终的打印信息:

可以看出uiHandler 接收信息处理信息的threadId和主线程的threadId是一样的,因为handler是在主线程中创建的(L:37),所以uiHandler会把消息传递到主线程,然后再主线程进行最终的ui刷新。不过消息是怎么传递处理的呢?说到handler的消息处理,就不得不提Looper、MessageQueue、Handler、Thread这四者之间的关系了,先上一张网上盗的图:

Thread是最基础的,Looper和MessageQueue都构建在Thread之上,Handler又构建在Looper和MessageQueue之上,我们通过Handler间接地与下面这几个相对底层一点的类打交道。
MessageQueue
讲messageQueue之前插播一下message
Message:包含描述和任意数据对象的消息,用于发送给Handler。

message对象很简单,两个int型的数据类型arg1和arg2是msg可以携带的简单数据,what代表msg的消息码,可以理解成让handler接收时明白你是哪一条消息,obj是Object类型的数据,值得注意的是当你arg0和arg1可以满足msg的内容的时候建议使用arg0和arg1,效率要比使用obj对象来的高的多。
MessageQueue:消息队列。内部存储着一组消息。对外提供了插入和删除的操作。MessageQueue内部是以单链表的数据结构来存储消息列表的。
每一个线程内部都维护了一个消息队列,在某一时刻我们点击了ui界面上的某一个按钮,然后有恰巧收到了程序的广播事件,这个时候该如何处理这两个事件呢?因为同一时刻只能处理意见事情,所以Android把点击按钮封装成了一个message,放到messagequeue里面,收到广播也封装成一个message,放到messagequeue,俗称入栈到消息队列,messageQueue就是一堆消息的消息池,线程Thread会一次从消息队列中取出消息进行处理。message按照“先进先出”的原则存放消息,存放并非实际意义的保存,而是将Message对象以链表的方式串联起来的。MessageQueue对象不需要我们自己创建,而是有Looper对象对其进行管理,一个线程最多只可以拥有一个MessageQueue。
Looper
Looper又称消息泵,主要作用是与当前线程创建一个绑定关系,同时创建一个messageQueue,默认情况下开启一个新的线程是不会开启消息循环的(主线程除外),而在子线程中如果想要new Handler()的话需要先调用Looper.prepare(),然后通过Looper.loop()让Looper开始工作,从消息队列里面取消息,将消息发送给对应的处理者(handler),让messageQueue中的消息循环起来。
Handler消息处理机制详解的更多相关文章
- 【转载】Android异步消息处理机制详解及源码分析
PS一句:最终还是选择CSDN来整理发表这几年的知识点,该文章平行迁移到CSDN.因为CSDN也支持MarkDown语法了,牛逼啊! [工匠若水 http://blog.csdn.net/yanbob ...
- Android应用AsyncTask处理机制详解及源码分析
1 背景 Android异步处理机制一直都是Android的一个核心,也是应用工程师面试的一个知识点.前面我们分析了Handler异步机制原理(不了解的可以阅读我的<Android异步消息处理机 ...
- 【转载】Android应用AsyncTask处理机制详解及源码分析
[工匠若水 http://blog.csdn.net/yanbober 转载烦请注明出处,尊重分享成果] 1 背景 Android异步处理机制一直都是Android的一个核心,也是应用工程师面试的一个 ...
- ThreadPoolExecutor运转机制详解
ThreadPoolExecutor运转机制详解 - 走向架构师之路 - 博客频道 - CSDN.NET 最近发现几起对ThreadPoolExecutor的误用,其中包括自己,发现都是因为没有仔细看 ...
- Java 反射 设计模式 动态代理机制详解 [ 转载 ]
Java 反射 设计模式 动态代理机制详解 [ 转载 ] @author 亦山 原文链接:http://blog.csdn.net/luanlouis/article/details/24589193 ...
- iOS的消息转发机制详解
iOS开发过程中,有一类的错误会经常遇到,就是找不到所调用的方法,当然这类问题比较好解决,给当前对象或其父类对象添加该方法即可,使得编译器在编译时能正确找到该方法:或者,还有另外的方法,由于Objec ...
- 【转】java的动态代理机制详解
java的动态代理机制详解 在学习Spring的时候,我们知道Spring主要有两大思想,一个是IoC,另一个就是AOP,对于IoC,依赖注入就不用多说了,而对于Spring的核心AOP来说,我们 ...
- java异常处理机制详解
java异常处理机制详解 程序很难做到完美,不免有各种各样的异常.比如程序本身有bug,比如程序打印时打印机没有纸了,比如内存不足.为了解决这些异常,我们需要知道异常发生的原因.对于一些常见的异常,我 ...
- 从mixin到new和prototype:Javascript原型机制详解
从mixin到new和prototype:Javascript原型机制详解 这是一篇markdown格式的文章,更好的阅读体验请访问我的github,移动端请访问我的博客 继承是为了实现方法的复用 ...
随机推荐
- Swift5 语言指南(十七) 反初始化
一个deinitializer一个类的实例被释放之前立即调用.您使用deinit关键字编写deinitializers ,类似于使用init关键字编写初始化程序的方式.Deinitializers仅适 ...
- Python3入门机器学习经典算法与应用
<Python3入门机器学习经典算法与应用> 章节第1章 欢迎来到 Python3 玩转机器学习1-1 什么是机器学习1-2 课程涵盖的内容和理念1-3 课程所使用的主要技术栈第2章 机器 ...
- Linux - 创建定时任务
crontab命令 用来创建周期性定时任务 crontab {-l|-r|-e} -l 显示当前的 crontab -r 删除当前的 crontab -e 使用编辑器编辑当前 crontab 文件 输 ...
- javascript实现二分法
js 实现数组查找二分法 二分法实现原理:二分查找可以解决已经排好序数组的查找问题:只要数组中包含target(即要查找的值),那么通过不断缩小包含target数组的范围,最终就可以找到它. 其算法流 ...
- Java language
1.Java开发环境: java编译运行过程: 1. 编译期:.java源文件,经过编译,生成.class字节码文件 2. 运行期:JVM加载.class并运行.class - 特点:跨平台.一次编程 ...
- Mac下搭建react及bable
1.安装node 下载: https://nodejs.org/en/download/ 测试--->返回版本号即为安装成功: $ node -v $ npm -v 2.安装全局create-r ...
- [COI2007] Sabor
下面给出这道一脸不可做的题的鬼畜性质: 1)对于一个点来说,其归属状态是确定的:走不到.A党或B党 .(黑白格染色) 方便起见,将包含所有不可达的点的极小矩形向外扩展一圈,设为矩形M. 2)矩形M的最 ...
- [HAOI2017] 新型城市化
给出的图中恰包含2个团,则图的补图为一个二分图,其最大独立集为原图的最大团. 我们知道,二分图的最大独立集=V-最小顶点覆盖,最小顶点覆盖=最大匹配. 问题转化为:计算删去后最大匹配减小的边集. 所以 ...
- web自动化测试(java)---元素定位
和python类似,java-selenium也提供了很多种元素定位的方法,具体如下: findElement(By.id()) findElement(By.name()) findElement( ...
- [Umbraco] umbraco中如何分页
分页功能应该说是web开发中最基本的功能了,常规的做法是通过查询sql语句进行分页数据显示.但在umbraco中却不是这样子的.而且通过xpath中的postion来定位.如下代码 <?xml ...