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,移动端请访问我的博客 继承是为了实现方法的复用 ...
随机推荐
- log4j 详细使用教程【转载】
日志是应用软件中不可缺少的部分,Apache的开源项目log4j是一个功能强大的日志组件,提供方便的日志记录.在apache网站:jakarta.apache.org/log4j 可以免费下载到Log ...
- python中的基本数值计算
最近用到了python的数字信号处理,发现很多以前学的都忘掉了,这里做个笔记 # -*- coding: utf-8 -*- #计算乘方 print pow(3,4) #计算平方 import num ...
- JS 实现九宫格算法
九宫格算法核心: 利用控件索引index计算出控件所在的行数和列数: 利用控件计算出left距离: 利用控件计算出top距离: 写特效时需要用到定位 公式: 行 row=parseInt(i/cols ...
- Java 基础学习总结(一)抽象类和接口
接触java的时间不是很长,以前对抽象类和接口的定义和区别也是模糊不清,最近拿起学校的教程读了起来,也参阅了网上的博客大神理解和总结,于是决定自己按照自己的理解来总结一下. 抽象类(半成品) 一般 ...
- docker学习篇(二)---- 基础篇
引言 在之前的学习中,我知道了docker的三大组件分别是----镜像,容器,仓库.了解了这三个组件也就初步理解了docker.所以我学习了这三个组件,并记录下来. 镜像 docker在运行一个容器时 ...
- Python基础教程(第3版) 笔记(一)
1.1 数和表达式: 除法运算的结果为小数,即浮点数 >>>1/2 0.5 除法运算为整数,使用双斜杠 >>>1//2 0 >>>5.0//2.4 ...
- [视频]K8飞刀 解密菜刀后门教程
链接:https://pan.baidu.com/s/1raC1S_njxeqS7TaiTN6jLA 提取码:otmb
- Redis主从和集群
主从概念 一个master可以拥有多个slave,一个slave又可以拥有多个slave.如此下去,形成了强大的多级服务器集群架构. master用写数据,经统计:网站的读写比率是10:1 通过主从分 ...
- Java gc中的那些事
我们已经知道Java堆是被所有线程共享的一块内存区域,所有对象实例和数组都在堆栈进行内存分配.为了进行高效的垃圾回收,虚拟机把堆内存划分成新生代年代(旧一代)和永久代(永久代)3个区域. 新生代 新生 ...
- 关于小窗滑动,父级body也跟随滑动的解决方案
需求:当前页面是信息列表,所以高度由内容自动填充, 所以页面可以上下滑动,加载更多, 但是下发物料一栏又为一个列表 所以做了一个弹窗框,因为是列表所以高度自然又是不可控的,所以给了一个最大高度,当超出 ...