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那些事的更多相关文章

  1. 深入源代码解析Android中的Handler,Message,MessageQueue,Looper

    本文主要是对Handler和消息循环的实现原理进行源代码分析.假设不熟悉Handler能够參见博文< Android中Handler的使用>,里面对Android为何以引入Handler机 ...

  2. Android之Handler源代码深入解析

    闲着没事.就来看看源代码,看看源代码的各种原理,会用仅仅是简单的,知道为什么才是最牛逼的. Handler源代码分析那,从使用的步骤来边用边分析: 1.创建一个Handler对象:new Handle ...

  3. Handler Looper 解析

    文章讲述Looper/MessageQueue/Handler/HandlerThread相关的技能和使用方法. 什么是Looper?Looper有什么作用? Looper是用于给线程(Thread) ...

  4. FrameWork内核解析之Handler消息机制(二)

    阿里P7Android高级架构进阶视频(内含Handler视频讲解)免费学习请点击:https://space.bilibili.com/474380680 一.Handler 在Android开发的 ...

  5. Android EventBus源代码解析 带你深入理解EventBus

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/40920453,本文出自:[张鸿洋的博客] 上一篇带大家初步了解了EventBus ...

  6. Android源代码解析之(四)--&gt;HandlerThread

    转载请标明出处:一片枫叶的专栏 上一篇文章中我们解说了AsyncTast的基本使用以及实现原理,我们知道AsyncTask内部是通过线程池和Handler实现的.通过对线程池和handler的封装实现 ...

  7. Android xUtils3源代码解析之网络模块

    本文已授权微信公众号<非著名程序猿>原创首发,转载请务必注明出处. xUtils3源代码解析系列 一. Android xUtils3源代码解析之网络模块 二. Android xUtil ...

  8. Android源代码解析之(三)--&gt;异步任务AsyncTask

    转载请标明出处:一片枫叶的专栏 上一篇文章中我们解说了android中的异步消息机制. 主要解说了Handler对象的使用方式.消息的发送流程等.android的异步消息机制是android中多任务处 ...

  9. Android源代码解析之(十三)--&gt;apk安装流程

    转载请标明出处:一片枫叶的专栏 上一篇文章中给大家分析了一下android系统启动之后调用PackageManagerService服务并解析系统特定文件夹.解析apk文件并安装的过程,这个安装过程实 ...

随机推荐

  1. Inno Setup入门(十九)——Inno Setup类参考(5)

    单选按钮 单选按钮在安装中也很常见,例如同一个程序可以选择安装不同的性质的功能,例如选择32位或者64位等,两者是排他性的,因此可以通过单选按钮(RadioButton)来实现,在同一个容器中放置的单 ...

  2. JavaScript里的循环方法:forEach,for-in,for-of

    JavaScript诞生已经有20多年了,我们一直使用的用来循环一个数组的方法是这样的: for (var index = 0; index < myArray.length; index++) ...

  3. Android内存优化1 了解java内存分配 1

    开篇废话 今天我们一起来学习JVM的内存分配,主要目的是为我们Android内存优化打下基础. 一直在想以什么样的方式来呈现这个知识点才能让我们易于理解,最终决定使用方法为:图解+源代码分析. 欢迎访 ...

  4. easyui-combobox绑定回车事件注意事项

    回车事件的定义的位置必须是easyui-combobox数据加载的后面,才有效果. HTML文件: <select id="aucBrandNo" class="e ...

  5. TCP为何采用三次握手来建立连接,若采用二次握手可以吗?

    首先简单介绍一下TCP三次握手     在TCP/IP协议中,TCP协议提供可靠的连接服务,采用三次握手建立一个连接. 第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_ ...

  6. python 如何调用子文件下的模块

    在python开发中,经常会出现调用子文件夹下的py模块 如上图,如果在test.py文件中,要调用meeting文件夹下面的huodongshu.py 模块, 直接在test.py 中 import ...

  7. UVa 615 - Is It A Tree?

    题目:给你一些有向边(端点,长度为1).推断给定的图是否是一棵树. 分析:图论.并查集.树是一个全部点都连接的有向无环图(不连接的是森林). 依照树的定义推断是否有环就可以,有环分成两种: 1.链状环 ...

  8. RocketMQ概念整理

    DefaultMessageStore 消息的存储和提取. 相对重要的两个方法: 消息存储 PutMessageResult putMessage(MessageExtBrokerInner msg) ...

  9. 转: windows下C++ UI库 UI神器-SOUI

    转:http://www.cnblogs.com/setoutsoft/p/4996870.html 前言 在Windows平台上开发客户端产品是一个非常痛苦的过程,特别是还要用C++的时候.尽管很多 ...

  10. [Android Pro] Notification的使用

    Android 4.0以前: 1: 普通的notification private static final int NOTIFY_ID = 0; notificationManager = (Not ...