文章目录

  • 前言
  • 基本使用
    • 发送和处理Runnable
    • 发送和处理Message
  • 流程梳理
    • 获取消息
    • 发送消息
    • 消息入队
    • 消息出队
  • 理解
  • 源码分析

前言

Handler 是Android 的消息处理机制,其主要有两个作用:

1.发送消息,延迟处理。你可以通过Handler 来发送一个Message 或者Runnable 对象,并在收到消息时处理他们,另外可以指定延迟时间,以便在将来执行。

2.线程间通讯。简单来说就是在不同于Handler 所属的线程发送消息,在Handler 的依附线程中接受并处理消息。这也就要求Handler 实例必须与线程和线程的消息队列相关联,当创建一个新的Handler对象时,需要绑定到创建它的线程和线程的消息队列上,通过将Message/Runnable 添加到消息队列中,在它们从消息队列中出来时执行。

Handler 是整个消息机制的门面类,用来发送和接收消息。提供了两种形式的消息分发和处理,一种是post 一个Runnable 对象,另外一种是send 一个Message对象。

基本使用

发送和处理Runnable

Handler 支持通过 post 的相关方法来发送一个 Runnable 对象进入消息队列,当收到相应的消息时被调用。相关的方法有{@link #post}, {@link #postAtTime(Runnable, long)}, {@link #postDelayed}

Handler handler = new Handler();Runnable runnable = new Runnable() {@Overridepublic void run() {// todo something}
}// 立即发送
handler.post(runnable);

其他API介绍:

android.os.Handler#postDelayed(java.lang.Runnable, long)
将Runnable 添加到消息队里中,并在指定的延迟后执行

android.os.Handler#postAtTime(java.lang.Runnable, long)
将Runnable 添加到消息队里中,并在指定的时间执行

发送和处理Message

Handler 允许发送一个 message对象,实现 Handler的{@link #handleMessage}方法,在这里处理接收到的Message。相关的方法有{@link #sendEmptyMessage}, {@link #sendMessage}, {@link #sendMessageAtTime}, {@link #sendMessageDelayed} 等

private Handler mHandler = new Handler(){@Overridepublic void handleMessage(Message msg) {super.handleMessage(msg);// 处理消息 message}
};// 获取 message
Message message = mHandler.obtainMessage(0);
// 发送 message
mHandler.sendMessage(message);

其他API介绍:

android.os.Handler#sendMessageDelayed
将Message 添加到消息队里中,并在指定的延迟后发送,在handler的 handleMessage 中处理消息

android.os.Handler#sendMessageAtTime
将Message 添加到消息队里中,并在指定的延迟后发送,在handler的 handleMessage 中处理消息

流程梳理

使用Handler 发送一个Message时,在 MessageQueue 的enqueueMessage 方法中会对消息按时间优先级进行入队操作。
与线程绑定的Looper 不断的从MessageQueue中取消息进行发送(queue.next()),当某个Message 执行完毕后,释放资源并加入到缓存队列中以重复使用(msg.recycleUnchecked())

获取消息

虽然Message的构造函数是公共的,我们可以通过new 关键字来自行创建一个Message 对象,但是系统更推荐我们使用 {Message.obtain()}或{Handler#obtainMessage.obtainMessage()}相关的方法获取对象。

Handler 的消息获取内部采用了享元模式来实现,Message 内部有一个全局的缓存池sPool,保存着回收的Message 对象。当使用obtain() 方法时,会先从缓存池中获取Message 对象,如果没有再去创建一个新对象。在消息转发完成后,会对使用的消息进行回收再利用,节约因频繁创建对象带来的内存开销。

发送消息

Handler 提供了很多的 send 和post 的方法,这些方法最终都会走到android.os.Handler#enqueueMessage 这个方法,而在这个方法里又会调用MessageQueue 的enqueueMessage 方法执行消息的入队操作。

    private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {msg.target = this;if (mAsynchronous) {msg.setAsynchronous(true);}return queue.enqueueMessage(msg, uptimeMillis);}

消息入队

MessageQueue 内部维护了一个消息队列,而 enqueueMessage(Message msg, long when) 方法主要处理的就是入队操作,对新来的Message 根据绝对时间进行优先级排序,绝对时间小的Message往前排。

boolean enqueueMessage(Message msg, long when) {...省略其他代码msg.when = when;Message p = mMessages;if (p == null || when == 0 || when < p.when) {// New head, wake up the event queue if blocked.msg.next = p;mMessages = msg;} else {...省略其他代码Message prev;for (;;) {prev = p;p = p.next;if (p == null || when < p.when) {break;}...省略其他代码}msg.next = p; // invariant: p == prev.nextprev.next = msg;}...省略其他代码
}

消息出队

在Handler 机制中,Looper类的主要作用是负责线程的消息循环,在Looper.loop() 方法中,循环不断的从MessageQueue.next() 函数中获取下一个消息进行派发,在发送完毕后回收释放该消息,完成消息的出队。

public static void loop() {final Looper me = myLooper();...省略其他代码final MessageQueue queue = me.mQueue;for (;;) {// 从消息队列中获取下一个要执行的MessageMessage msg = queue.next(); // might block...省略其他代码// 执行消息的分发msg.target.dispatchMessage(msg);...省略其他代码// 释放、回收Message,完成消息出队msg.recycleUnchecked();}
}

理解

Handler:是消息机制的门面类,主要负责发送和处理消息,同样还有移除消息的功能。
Message:即要发送的消息,包含消息标记、消息数据、执行时间、处理响应的Handler等。
MessageQueue:内部包含一个由Looper调度的消息队列
Looper:负责线程的消息循环,从MessageQueue 中获取要发送的消息

以一家运输公司做个比喻

运输公司(Handler):承接货物的运输业务,负责货物的接受和发送。
运输车(Message):货物的载体,附带一些信息,比如所属公司(Handler)、编号(what)、运输的货物(arg1、arg2、obj)、发车时间(when)等等
备用车辆(Message.sPool):空闲状态的运输车,当有新需求的时候负责提供运输车辆
执行运输任务的车队(MessageQueue.mMessages):因任务而组成的运输车队,根据每辆车发车时间进行车辆排序。
调度站(Looper):负责对运输的车队车辆进行逐个派发

当客户有需求时,运输公司会从空闲的运输车中安排一辆车为其服务,货物打包好后加入执行运输任务的车队中。运输车队对新加入的运输车辆按发车时间进行排序。另一边,调度站如果发现有要执行任务的车队,则逐个对运输车辆进行派发,“下一辆、下一辆…”,如果没有,则处于等待的状态。运输车辆执行完当前任务后,把携带的信息清空,加入到备用车辆中,以供下次继续使用。

源码分析

本篇先对Handler 机制做个大概的介绍,源码部分将对Message、MessageQueue、Looper 分别做分析。

Handler消息机制介绍,流程梳理相关推荐

  1. Android Framework学习(八)之Handler消息机制(Native层)解析

    在深入解析Android中Handler消息机制一文中,我们学习了Handler消息机制的java层代码,这次我们来学习Handler消息机制的native层代码. 在Java层的消息处理机制中,Me ...

  2. Handler消息机制详解

    Handler机制是Android开发中最常见的机制,可以说贯穿整个Android,在探究Handler机制原理之前,我们先来捋一下用法 1.handler.post(Runnable) 2.hand ...

  3. Android Handler消息机制不完全解析

    1.Handler的作用 Android开发中,我们经常使用Handler进行页面的更新.例如我们需要在一个下载任务完成后,去更新我们的UI效果,因为AndroidUI操作不是线程安全的,也就意味着我 ...

  4. Android进阶知识树——Android Handler消息机制

    1.概述 在安卓程序启动时,会默认在主线程中 运行程序,那如果执行一些耗时的操作则UI就会处于阻塞状态,出现界面卡顿的现象,再者用户的多种操作,系统是如何做到一一处理的,系统又是如何管理这些任务的,答 ...

  5. Win32窗口机制和消息机制整体流程

    [ 摘要] 本节课通过一张图,详细的介绍了Windows的窗口机制和消息机制整体流程,让你一目了然. Windows系统,是窗口作为基础的系统,以消息机制作为运转机制的系统.我们学习Windows编程 ...

  6. Android Handler消息机制源码解析

    好记性不如烂笔头,今天来分析一下Handler的源码实现 Handler机制是Android系统的基础,是多线程之间切换的基础.下面我们分析一下Handler的源码实现. Handler消息机制有4个 ...

  7. handler消息机制入门

    handler消息机制入门 为什么要用handle? 我们在网络上读取图片信息时,是不能把耗时操作放在主线程里面的,当我们在子线程中获取到了图片的消息的时候,我们就需要把这个数据传给主线程. 而直接使 ...

  8. Android Handler消息机制源码分析

    一,前言 众多周知, Android 只允许在主线程中更新UI,因此主线程也称为UI线程(ActivityThread). 如此设计原因有二: (1) 由于UI操作的方法都不是线程安全的,如果多个线程 ...

  9. Handler消息机制-Native层

    Handler消息机制-Native层 android12-release Handler消息机制-FWK层 1. MessageQueue连接Native层 1.1 nativeInit初始化 Na ...

最新文章

  1. mysql全量和增量备份脚本
  2. CentOS系统Yum源配置
  3. java php python 高并发_关于php如何调用Python快速发送高并发邮件的示例代码
  4. linux系统读取excel文件是否存在,小弟我用poi读excel,在window下没有有关问题,但把程序放到linux上时,读取客户端的excel文件报错,不...
  5. iframe高度自适应,终于解决了
  6. 矩阵运算_Eigen使用_基本数据类型
  7. 【数字信号调制】基于matlab GUI数字信号调制系统【含Matlab源码 1030期】
  8. pcb边框是自己画_说一下Altium Designer软件画不规则PCB板边框的方法
  9. 未来教育MySQL题库下载_未来教育考试系统(通用下载管理版)可在线下载最新试题,支持章节练习...
  10. JAVA JNI调用科大讯飞离线语音合成Windows
  11. linux亮度调节指令,Linux Mint 亮度调节——xrandr命令学习
  12. java 调停者模式_[Java教程]《JAVA与模式》之调停者模式
  13. 走近国内同人游戏开发者 一探游戏开发的喜与悲
  14. 天才小毒妃 第961章 她不后悔就够了
  15. el-cascader 级联选器中实现任意级别都可选,且前两级别为必选
  16. Google收购Moto:天使还是魔鬼?
  17. 千锋和蓝欧html5,蓝鸥零基础学习HTML5第六讲 CSS的常见样式
  18. python画函数图像网格_用python 画一个网格
  19. 前端Object.assign
  20. mysql数据恢复工具_mysql文件恢复软件|Mysql数据库修复工具(Recovery for MySQL)下载 V2.7.22255.1 官方版 - 比克尔下载...

热门文章

  1. token 微信access 过期_微信开发ACCESS TOKEN 过期失效解决方案
  2. 念整数(你的程序要读入一个整数,范围是[-100000,100000]。然后,用汉语拼音将这个整数的每一位输出出来。 如输入1234,则输出: yi er san si)
  3. 黑苹果睡眠唤醒usb失灵_黑苹果解决USB3.0驱动问题
  4. Go语言学习之net/http包(The way to go)
  5. React 面试题 回答
  6. 何帅:“在线”思考,王坚的云计算心理学
  7. 路由器有线优先吗_如何设置有线上网优先 - 卡饭网
  8. 自然语言处理之维特比(Viterbi)算法
  9. 李飞飞划重点的「具身智能」,走到哪一步了?
  10. Win10恢复照片查看器