Android Handler 机制实现原理分析

handler在安卓开发中是必须掌握的技术,但是很多人都是停留在使用阶段。使用起来很简单,就两个步骤,在主线程重写handler的handleMessage( )方法,在工作线程发送消息。但是,有没有人想过这种技术是怎么实现的呢?下面我们一起探讨下。

先上图,让大家好理解下handler机制:

handler机制示例图

上面一共出现了几种类,ActivityThread,Handler,MessageQueue,Looper,msg(Message),对这些类作简要介绍:

ActivityThread:程序的启动入口,为什么要介绍这个类,是因为该类就是我们说的主线程,它对Looper进行操作的。

Handler:字面意思是操控者,该类有比较重要的地方,就是通过handler来发送消息(sendMessage)到MessageQueue和 操作控件的更新(handleMessage)。handler下面持有这MessageQueue和Looper的对象。

MessageQueue:字面意思是消息队列,就是封装Message类。对Message进行插入和取出操作。

Message:这个类是封装消息体并被发送到MessageQueue中的,给类是通过链表实现的,其好处方便MessageQueue的插入和取出操作。还有一些字段是(int what,Object obj,int arg1,int arg2)。what是用户定义的消息和代码,以便接收者(handler)知道这个是关于什么的。obj是用来传输任意对象的,arg1和arg2是用来传递一些简单的整数类型的。

下面,我们按照启动顺序来进行源码分析:

从上面可以看出,ActivityThread类是用来启动Android的,其源码为:

ActivityThread类:

接下来,我们看到Looper类了,我们进去看看里面的源码实现:

首先,我们看看里面有哪些字段:

Looper的内部属性

然后我们迫不及待地要想去看看prepareMainLooper方法,到底干了什么

Looper.prepareMainLooper()方法

这里我们可以看到,prepareMainLooper是为了设置一个持有消息队列和消息序列器的Looper进去ThreadLocal。接下来我们看看loop方法吧:

Looper.loop()方法

我们可以看到loop方法中,会取出内部的消息序列器,并且迭代里面的消息,根据消息的target分发消息(到handleMessage方法中)。如果你有疑问,你应该是不清楚Looper的MessageQueue为什么会有Message。那么我们就马上去看,到底是哪里添加消息的。话说,到了这里我也好像没有分析到和我们handler相关的操作吧。因为你和我都知道handler的作用是sendMessage和handleMessage,所以我们知道,Looper中的消息序列器的消息体,肯定是从sendMessage中添加进去的。不墨迹,我们马上进入Handler的源码分析。

首先,我们先看看Handler的字段:

Handler的字段

接着,我们看看Handler的构造方法,我们可以看到,Handler有两类构造方法(别看到6个,它们都是往这两种方法调用的):

Handler的构造方法

接着,我们要进入Handler.dispatchMessage()方法,因为我们要解释上面刚刚Looper.loop方法。dispatchMessage的方法很简单,只有三个方向,其源码为:

Handler.dispatchMessage()方法

到这里为止,执行代码就结束了。那么问题来了,消息从哪里来的?带着这个疑问,我们马上进入Handler.sendMessage()逻辑去看看,其源码是:

Handler.sendMessage()方法

好不容易找到了发送消息的逻辑并理解了,但是还要去壳,在MessageQueue中分析了,首先,我们回顾下,消息序列器是在Looper.prepare()中初始化的。MessageQueue源码,构造方法很简单:

MessageQueue构造方法

然后我们再到达MessageQueue.enqueueMessage()方法中看源码:

MessageQueue.enqueueMessage()方法

这个是发送消息的最终执行代码,就是把消息放进消息序列器。在Looper.loop()方法中,我们是需要不断从消息序列器中取出消息的。其过程也是我们可以进去MessageQueue.next()的源码中看看:

MessageQueue.next()方法

这样,整个过程就完成了。在这些执行过程中,Message是它们的物件。我们可以看看Message的结构:

Message的字段

除此之外,Message的数据结构是基于链表的,方法都很简单的,我就不贴出来了。

总结一下,其实就是用一个ThreadLocal来存储对象,然后在执行的时候,能够保证对象的不变形,这样就能达到在主先线程更新UI了。

以上就是对Android Handler 进行的详解,后续继续整理相关资料,谢谢大家对本站的支持!

(0)

相关推荐

  • Android 中Handler引起的内存泄露

    在Android常用编程中,Handler在进行异步操作并处理返回结果时经常被使用.通常我们的代码会这样实现. public class SampleActivity extends Activity { private final Handler mLeakyHandler = new Handler() { @Override public void handleMessage(Message msg) { // ... } } } 但是,其实上面的代码可能导致内存泄露,当你使用Androi

  • Android中Handler实现倒计时的两种方式

    背景: 最近项目中,正好做到登录/注册这个功能块.它需要通过发送验证码,在规定的时间内用验证码来完成登录/注册.之前的项目中也有这个功能,但是觉得太复杂了,只好自己重新实现一遍.用Handler来做,觉得代码简介,逻辑也清楚. 代码一: //在向服务端发送获取验证码成功的回调函数中,开始发消息: mHandler.obtainMessage(); mHandler.sendEmptyMessage(MSG_CODE); //消息的处理: private static final int MSG_

  • Android Handler的详解及实例

    Android Handler的详解 Handler我们常常用于通知主线程做相对应的操作,但是如果使用不但的话就会造成内存泄露,所以记录写正确的Handler写法. Handler handler = new Handler() { public void handleMessage(Message msg) { //do something }; }; handler.sendEmptyMessageDelayed(0, 100 * 1000); 像上面的代码片段,就会存在内存泄露的风险,因为

  • Android使用Handler实现View弹性滑动

    弹性滑动原理 将一次大的滑动非为若干次小的滑动,并在一个时间段内完成.更好的用户体验 实现方式很多种,包括用Scroller,动画,延时策略. 使用Handler实现弹性滑动 效果可以看到按钮Button向滑动.注意这里是将View的内容改变. 你可以试一试将Button外层的RelitiveLayout去掉,把id放在Button下.发现是Button的文字滑动 <RelativeLayout xmlns:android="http://schemas.android.com/apk/r

  • Android Handler移除Message详解及实例代码

    Android Handler移除Message详解 问题: 1.removeMessage(what)函数是否只能移除对应what值的Message? 2.对于Delayed发送的Message,能否提前remove? 代码测试: package javine.k.testhandler; import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.os.Han

  • Android 消息机制以及handler的内存泄露

    Handler 每个初学Android开发的都绕不开Handler这个"坎",为什么说是个坎呢,首先这是Android架构的精髓之一,其次大部分人都是知其然却不知其所以然.今天看到Handler.post这个方法之后决定再去翻翻源代码梳理一下Handler的实现机制. 异步更新UI 先来一个必背口诀"主线程不做耗时操作,子线程不更新UI",这个规定应该是初学必知的,那要怎么来解决口诀里的问题呢,这时候Handler就出现在我们面前了(AsyncTask也行,不过本质

  • Android HandlerThread的使用及原理详解

    一.HandlerThread的含义 HandlerThread能够新建拥有Looper的线程.这个Looper能够用来新建其他的Handler.(线程中的Looper)需要注意的是,新建的时候需要被回调. 二.HandlerThread的用法 一般情况下,我们会经常用Handler在子线程中更新UI线程,那是因为在主线程中有Looper循环,而HandlerThread新建拥有Looper的子线程又有什么用呢? 必然是执行耗时操作.举个例子,数据实时更新,我们每10秒需要切换一下显示的数据,如

  • Android用HandlerThread模拟AsyncTask功能(ThreadTask)

    前言 AsyncTask是个好东西,能处理绝大多数应用线程和更新UI的任务,由于其内部使用了静态线程池,如果你有一堆异步任务(例如全局定时更新数据.同一个Activity中多个AsyncTask同时执行)其中有不能马上执行完的情况(例如网络请求超时),那就糟了,其他任务都还等着呢,就会出现任务卡住的情况.此时就需要直接上Thread了,这里参考AsyncTask的API封装了一个ThreadTask,便于必要时代码替换,欢迎交流!  正文实例代码: import android.os.Handl

  • Android Handler 机制实现原理分析

    handler在安卓开发中是必须掌握的技术,但是很多人都是停留在使用阶段.使用起来很简单,就两个步骤,在主线程重写handler的handleMessage( )方法,在工作线程发送消息.但是,有没有人想过这种技术是怎么实现的呢?下面我们一起探讨下. 先上图,让大家好理解下handler机制: handler机制示例图 上面一共出现了几种类,ActivityThread,Handler,MessageQueue,Looper,msg(Message),对这些类作简要介绍: ActivityThr

  • Android  Handler 机制实现原理分析

    handler在安卓开发中是必须掌握的技术,但是很多人都是停留在使用阶段.使用起来很简单,就两个步骤,在主线程重写handler的handleMessage( )方法,在工作线程发送消息.但是,有没有人想过这种技术是怎么实现的呢?下面我们一起探讨下. 先上图,让大家好理解下handler机制: handler机制示例图 上面一共出现了几种类,ActivityThread,Handler,MessageQueue,Looper,msg(Message),对这些类作简要介绍: ActivityThr

  • Android Handler机制详解原理

    Looper是整个跨线程通信的管理者 // 内部持有的变量如下: ThreadLocal<Looper> MainLooper Observer MessageQueue Thread 1.首先先回忆一下Handler怎么用 Android线程通信分为以下两种情况 1.子线程发消息给UI线程 2.UI线程发消息给子线程 3.子线程发消息给另个子线程 1.子线程发消息给UI线程 class FragmentContentActivity : AppCompatActivity() { val F

  • Android AccessibilityService 事件分发原理分析总结

    目录 AccessibilityService 监听事件的调用逻辑 onAccessibilityEvent onIntercept AccessibilityService 事件的外部来源 AccessibilityServiceInfo AccessibilityManager AccessibilityManagerService AccessibilityServiceConnection 前言: 在了解了无障碍服务基础使用之后,我们来探究一下 AccessibilityService

  • 详解Android Handler机制和Looper Handler Message关系

    概述 我们就从以下六个问题来探讨Handler 机制和Looper.Handler.Message之前的关系? 1.一个线程有几个Handler? 2.一个线程有几个Looper?如何保证? 3.Handler内存泄漏原因?为什么其他的内部类没有说过这个问题? 4.为何主线程可以new Handler?如果在想要在子线程中new Handler 要做些什么准备? 5.子线程中维护的Looper,消息队列无消息的时候的处理方案是什么?有什么用? 6.Looper死循环为什么不会导致应用卡死? 一.

  • Android Handler机制的工作原理详析

    写在前面 上一次写完Binder学习笔记之后,再去看一遍Activity的启动流程,因为了解了Binder的基本原理,这次看印象会更深一点,学习效果也比以前好很多.本来打算直接来写Activity的启动流程的,但总觉得Handler也需要写一下,知道Handler和Binder的原理后,再去看Activity的启动流程,应该也没什么问题了.虽然网上已经有很多Handler相关的文章了,而且Handler机制的上层原理也并不难,还是决定写一下,因为我想构建自己的知识体系.也希望给看我博客的朋友们一

  • javascript垃圾收集机制的原理分析

    前面的话 javascript具有自动垃圾收集机制,执行环境会负责管理代码执行过程中使用的内存.在编写javascript程序时,开发人员不用再关心内存使用问题,所需内存的分配以及无用内存的回收完全实现了自动管理.下面将详细介绍javascript的垃圾收集机制 原理 垃圾收集机制的原理很简单:找出那些不再继续使用的变量,然后释放其占用的内存,垃圾收集器会按照固定的时间间隔,或代码执行中预定的收集时间,周期性地执行这一操作 局部变量只在函数执行的过程中存在.而在这个过程中,会为局部变量在栈(或堆

  • javascript类继承机制的原理分析

    目前 javascript的实现继承方式并不是通过"extend"关键字来实现的,而是通过 constructor function和prototype属性来实现继承.首先我们创建一个animal 类 js 代码 复制代码 代码如下: var animal = function (){ //这就是constructor function 了 this .name = 'pipi'; this .age = 10; this .height = 0; } //建立一个动物的实例 var

  • RAC cache fusion机制实现原理分析

    在单实例中,进程要想修改数据块,必须在数据块的当前版本(Currentcopy)上进行修改RAC环境也一样 这便涉及到一系列问题: 如何获得数据块的版本在集群节点间的分布图? 如何知道哪个节点拥有的是当前版本? 如何完成传递过程? 这一系列问题的解决依靠内存融合技术(cachefusion) cachefusion通过高速的privateinterconnect,在实例间进行数据块传递 这是RAC最核心的工作机制,他把所有实例的SGA虚拟成一个大的SGA区 每当不同的实例请求相同的数据块,这个数

  • kafka的消息存储机制和原理分析

    目录 消息的保存路径 数据分片 log分段 日志和索引文件内容分析 在 partition 中通过 offset 查找 message过程 日志的清除策略以及压缩策略 日志的清理策略有两个 日志压缩策略 消息写入的性能 顺序写 零拷贝 消息的保存路径 消息发送端发送消息到 broker 上以后,消息是如何持久化的? 数据分片 kafka 使用日志文件的方式来保存生产者和发送者的消息,每条消息都有一个 offset 值来表示它在分区中的偏移量. Kafka 中存储的一般都是海量的消息数据,为了避免

随机推荐