Handler源代码解析-有关Handler那些事
Handler被成为异步处理大师。相信大家都会用,面试中也常常会问到Handler的底层原理。今天就来看一看Handler的机制。
Android的消息处理有四个核心类:Handler、Looper、Message、MessageQueue,都在android.os包中。
Looper的字面意思是“循环器”,"轮询器"。它被设计用来使一个普通线程变成Looper线程。所谓Looper线程就是循环工作的线程。
在程序开发中(尤其是GUI开发中)。常常会须要一个线程不断循环,一旦有新任务则运行。运行完继续等待下一个任务,这就是Looper线程。
什么是handler?handler扮演了往MQ上加入消息和处理消息的角色(仅仅处理由自己发出的消息)。即通知MQ它要运行一个任务(sendMessage)。并在loop到自己的时候运行该任务(handleMessage),整个过程是异步的。
handler创建时会关联一个looper,默认的构造方法将关联当前线程的looper。
来看看Handler的官方凝视:

一个Handler能够让你用来发送和处理消息(Message)。以及消息上附带的Runnable对象。整个是跟消息队列(MessageQueue)一起使用的。每个Handler实例会关联到一个唯一的线程和该线程的MessageQueue。假设你创建了一个Handler,他将会跟创建这个Handler的线程和该线程的消息队列绑定在一起。也就是说通过把消息发往这个队列和在出列的时候处理他们。Handler一般有两种应用产景。(1)就是调度消息和runnable对象在未来的某个时间点运行(归纳起来就是消息的发送)。(2)能够把消息发送到其它线程里面。再简单概括一下就是Handler是跟创建他的线程绑定在一起的,然后通过消息队列方式,实现线程安全的操作。
Handler的创建

当我们调用send(),post()方法时。事实上是运行了这个:


第一句把msg.target设置为当前的handler本身。这一步非常重要,由于在这之后,就跟handler没关系了。后面会分析;接着就调用消息队列的入列方法把消息体丢到队列里面排队等待运行。
能够看到,无论是什么方式,终于都是把消息(runnable最后也是包装成消息)丢到消息队列里面。
接着是Looper的工作机制

这事实上就是一个生产者消费者的模型。在for循环里面,looper不断的订阅消息队列的下一个元素(next()方法)。然后调用Handler的dispatchMessage方式分发消息给handler进行处理。这里消息一个一个处理完之后才会处理下一个,是单线程串行运行的,并且跟创建handler的线程是同一个线程,所以完美的避免的线程安全的问题。那么你的疑问会是,到底是谁来调用这个loop方法的。不是会卡住吗?是的,这就是精髓所在,这里的looper是UI线程在初始化全然部的UI操作之后调用的,这样一来,就不会有卡住的问题了。
这里是消息分发的操作:

handleMessage方法是优先级最低的,由于有Handler有个post方法。參数是一个Runnable对象,然后通过创建一个Message,再把message的callback设置为这个runnable。然后再发送到消息队列里面。post方法的场景是你更新UI的时候须要知道获取到了什么新的数据。然后直接更新。而handleMessage方法能够不须要知道更新了哪些数据,就只更新UI就能够了。
handler之所以能够更新UI,不是系统做了什么奇妙般的兼容。而是由于他跟UI线程使用的本来就是同一个线程,UI线程通过Looper.loop来等待消息的分发,handler发送消息后把消息放到消息队列里面。而Looper负责从消息队列里面拿数据,又交给handler进行处理,终于实现了UI的异步更新操作。
这是个生产者消费者模型典型应用。当中消息队列的功劳巨大,我们来看看他有哪些功能。假设我们开发中也须要实现这样的类似的生产者消费者模型。能够使用这一套机制。
须要注意的是,MessageQueue我们不能单独定义来使用,由于其核心API的可訪问修饰符都是包级别的。我们不能把代码定义到android.os这个包以下。所以他要通过配合Looper来使用。Looper的核心API都是开放的。
enqueueMessage入列,能够把消息放到队列里面。这里队列的底层是android的本地代码实现的。事实上能够參照juc里面的DelayQueue的实现,机制差点儿相同,都支持延时出列的,这只是实现方式不同罢了。
next()出列,消息出列,队列的出列优先级是入列的时候定义的时间来决定的,时间值越小(长整形)优先级越高。
Handler源代码解析-有关Handler那些事的更多相关文章
- 深入源代码解析Android中的Handler,Message,MessageQueue,Looper
本文主要是对Handler和消息循环的实现原理进行源代码分析.假设不熟悉Handler能够參见博文< Android中Handler的使用>,里面对Android为何以引入Handler机 ...
- Android之Handler源代码深入解析
闲着没事.就来看看源代码,看看源代码的各种原理,会用仅仅是简单的,知道为什么才是最牛逼的. Handler源代码分析那,从使用的步骤来边用边分析: 1.创建一个Handler对象:new Handle ...
- Handler Looper 解析
文章讲述Looper/MessageQueue/Handler/HandlerThread相关的技能和使用方法. 什么是Looper?Looper有什么作用? Looper是用于给线程(Thread) ...
- FrameWork内核解析之Handler消息机制(二)
阿里P7Android高级架构进阶视频(内含Handler视频讲解)免费学习请点击:https://space.bilibili.com/474380680 一.Handler 在Android开发的 ...
- Android EventBus源代码解析 带你深入理解EventBus
转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/40920453,本文出自:[张鸿洋的博客] 上一篇带大家初步了解了EventBus ...
- Android源代码解析之(四)-->HandlerThread
转载请标明出处:一片枫叶的专栏 上一篇文章中我们解说了AsyncTast的基本使用以及实现原理,我们知道AsyncTask内部是通过线程池和Handler实现的.通过对线程池和handler的封装实现 ...
- Android xUtils3源代码解析之网络模块
本文已授权微信公众号<非著名程序猿>原创首发,转载请务必注明出处. xUtils3源代码解析系列 一. Android xUtils3源代码解析之网络模块 二. Android xUtil ...
- Android源代码解析之(三)-->异步任务AsyncTask
转载请标明出处:一片枫叶的专栏 上一篇文章中我们解说了android中的异步消息机制. 主要解说了Handler对象的使用方式.消息的发送流程等.android的异步消息机制是android中多任务处 ...
- Android源代码解析之(十三)-->apk安装流程
转载请标明出处:一片枫叶的专栏 上一篇文章中给大家分析了一下android系统启动之后调用PackageManagerService服务并解析系统特定文件夹.解析apk文件并安装的过程,这个安装过程实 ...
随机推荐
- [CF843D]Dynamic Shortest Path
[CF843D]Dynamic Shortest Path 题目大意: 给定一个带权有向图,包含\(n(n\le10^5)\)个点和\(m(m\le10^5)\)条边.共\(q(q\le2000)\) ...
- [POJ3728]The merchant
题目大意: 给你一棵n个结点的带权树,有q组询问,问你从u到v的路径上最大值与最小值的差(最大值在最小值后面). 思路: 首先考虑路径上合并两个子路径u->t和t->v时的情况. 假设我们 ...
- [转]MySQL 数据类型(二)
MySQL 的数值数据类型可以大致划分为两个类别,一个是整数,另一个是浮点数或小数.许多不同的子类型对这些类别中的每一个都是可用的,每个子类型支持不同大小的数据,并且 MySQL 允许我们指定数值字段 ...
- CentOS6安装NodeJS(非编译)
由于编译安装需要各种依赖库,会远远高于生产环境下的默认版本,强行升级会产生很多不必要的问题,所以一般用官网编译好的安装 下载nodejs并安装 wget https://nodejs.org/dist ...
- Elasticsearch-Kibana 5.5.1插件安装
说明:比如Elasticsearch的版本和Kibana的版本保持一致,方便排查问题.一切的安装的运行建议不要用root权限,最好是当前用户下的权限.Kibana版本变化有点快,不同的版本有不同的配置 ...
- ER TO SQL语句
ER TO SQL语句的转换,在数据库设计生命周期的位置如下所示. 一.转换的类别 从ER图转化得到关系数据库中的SQL表,一般可分为3类: 1)转化得到的SQL表与原始实体包含相同信息内容.该类转化 ...
- OCP升级(3.6->3.7)
有个好文档还是靠普很多,感谢同事的文档.升级步骤记录如下 1.检查现有环境 [root@master ~]# etcd --version etcd Version: Git SHA: 1674e68 ...
- leetcoder-50-Pow(x, n)
Pow(x, n) 能够直接用库函数pow(x,n)一步搞定,但明显这样就没意思了. 參考 快 速 幂 取 模 二分.复杂度为O(logn) 递归方法 class Solution { pub ...
- 关于typedef的用法总结(zz)
不管实在C还是C++代码中,typedef这个词都不少见,当然出现频率较高的还是在C代码中.typedef与#define有些相似,但更多 的是不同,特别是在一些复杂的用法上,就完全不同了,看了网上一 ...
- 【Docker】mesos如何修改hostport默认端口范围?
1.marathon文档:https://mesosphere.github.io/marathon/docs/native-docker.html Static port mapping: It's ...