当前位置: 首页 > news >正文

handler解析(4)-Message及Message回收机制

Message中可以携带的信息

Message中可以携带的数据比较丰富,下面对一些常用的数据进行了分析。

/*** 用户定义的消息代码,以便当接受到消息是关于什么的。其中每个Hanler都有自己的命名控件,不用担心会冲突*/ public int what;
/*** 如果你只想存很少的整形数据,那么可以考虑使用arg1与arg2,* 如果需要传输很多数据可以使用Message中的setData(Bundle bundle)*/public int arg1;
/*** 如果你只想存很少的整形数据,那么可以考虑使用arg1与arg2,* 如果需要传输很多数据可以使用Message中的setData(Bundle bundle)*/public int arg2;
/*** 发送给接受方的任意对象,在使用跨进程的时候要注意obj不能为null*/public Object obj;
/*** 在使用跨进程通信Messenger时,可以确定需要谁来接收*/public Messenger replyTo;
/*** 在使用跨进程通信Messenger时,可以确定需要发消息的uid*/public int sendingUid = -1;
/*** 如果数据比较多,可以直接使用Bundle进行数据的传递*/Bundle data;

创建消息的方式

官方建议使用Message.obtain()系列方法来获取Message实例,因为其Message实例是直接从Handler的消息池中获取的,可以循环利用,不必另外开辟内存空间,效率比直接使用new Message()创建实例要高。其中具体创建消息的方式,我已经为大家分好类了。具体分类如下:

//无参数
public static Message obtain() {...}
//带Messag参数
public static Message obtain(Message orig) {}
//带Handler参数
public static Message obtain(Handler h) {}
public static Message obtain(Handler h, Runnable callback){}
public static Message obtain(Handler h, int what){}
public static Message obtain(Handler h, int what, Object obj){}
public static Message obtain(Handler h, int what, int arg1, int arg2){}
public static Message obtain(Handler h, int what,int arg1, int arg2, Object obj) {}

其中在Message的obtain带参数的方法中,内部都会调用无参的obtain()方法来获取消息后。然后并根据其传入的参数,对Message进行赋值。(关于具体的obtain方法会在下方消息池实现原理中具体描述)

消息池实现原理

 既然官方建议使用消息池来获取消息,那么在了解其内部机制之前,我们来看看Message中的消息池的设计。具体代码如下:

private static final Object sPoolSync = new Object();//控制获取从消息池中获取消息。保证线程安全
private static Message sPool;//消息池
private static int sPoolSize = 0;//消息池中回收的消息数量
private static final int MAX_POOL_SIZE = 50;//消息池最大容量
// sometimes we store linked lists of these things@UnsupportedAppUsage/*package*/ Message next;public static Message obtain() {synchronized (sPoolSync) {if (sPool != null) {Message m = sPool;sPool = m.next;m.next = null;m.flags = 0; //重新标识当前Message没有使用过sPoolSize--;return m;}}return new Message();//如果为空直接返回}

从中我们发现如果sPool如果不为null,则返回直接new一个Message返回,整个方法结束,那么sPool是什么,sPool是一个message,从源码中我们可以发现sPool其实就相当于一个头指针,指向缓存池中第一个缓存的Message,如果sPool不为null则说明缓存池中存在空闲的Message,返回缓存池中空闲的message,然后sPool执行下一个缓存message对象,然后将msg.next重置为0,整体代码过下来,我们发现Message的缓存池其实就是用了一个数据结构-单向链表。具体流程如图:

这块就很明显是消息池的取出了,那么它的存是在哪里呢,全局搜sPool,我们发现在recycleUncheck中有实现

   /*** Recycles a Message that may be in-use.* Used internally by the MessageQueue and Looper when disposing of queued Messages.*/@UnsupportedAppUsagevoid recycleUnchecked() {// Mark the message as in use while it remains in the recycled object pool.// Clear out all other details.flags = FLAG_IN_USE;what = 0;arg1 = 0;arg2 = 0;obj = null;replyTo = null;sendingUid = UID_NONE;workSourceUid = UID_NONE;when = 0;target = null;callback = null;data = null;synchronized (sPoolSync) {if (sPoolSize < MAX_POOL_SIZE) {next = sPool;sPool = this;sPoolSize++;}}}

然后这块代码又是在recycle中调用的

 /*** Return a Message instance to the global pool.* <p>* You MUST NOT touch the Message after calling this function because it has* effectively been freed.  It is an error to recycle a message that is currently* enqueued or that is in the process of being delivered to a Handler.* </p>*/public void recycle() {if (isInUse()) {if (gCheckRecycle) {throw new IllegalStateException("This message cannot be recycled because it "+ "is still in use.");}return;}recycleUnchecked();}

这块首先判断消息是否在使用之中,如果在使用之中,继续判断gCheckRecycle,gCheckRecycle的默认值是true,如果不在使用之中,最后会走进recycleUnchecked。

然后来分析recycleUnChecked

一开始,把这个消息所有成员赋值成最初的状态,FLAG_IN_USE的值是1一开始说了Message的flags表示这个Message有没有在使用,1表示在池中,等待复用,0表示正在被使用。重点看同步锁中的代码。

假设全局池没有元素时,我们将第一个消息放到池中,sPool一开始是NULL,next指向了sPool,所以此时的消息的sPool和next都是NULL,然后sPool指向当前的Message对象,最后池的数量加1。大致如下图。

假设有来个消息m2,在走一遍同步锁中的代码,此时全局池的状态如下图所示。

其他几个类似

相关文章:

handler解析(4)-Message及Message回收机制

Message中可以携带的信息 Message中可以携带的数据比较丰富&#xff0c;下面对一些常用的数据进行了分析。 /*** 用户定义的消息代码&#xff0c;以便当接受到消息是关于什么的。其中每个Hanler都有自己的命名控件&#xff0c;不用担心会冲突*/ public int what; /*** 如果你…...

Linux使用定时任务监控java进程并拉起

需求描述&#xff1a; 设计一个脚本&#xff0c;通过Linux定时任务&#xff0c;每分钟执行一次&#xff0c;监控jar包进程是否存在&#xff0c;存在则不做动作&#xff0c;不存在则重新拉起jar包程序。 定时任务配置&#xff1a; */1 * * * * bash -x /root/myfile/jars/che…...

Win 10电脑摄像头提示错误代码0xa00f4244怎么办?

如果你的Windows 10电脑无法打开摄像头&#xff0c;提示“我们找不到你的摄像头”的错误消息&#xff0c;错误代码是0xA00F4244&#xff0c;原因可能是杀毒软件阻止了摄像头&#xff0c;或者是摄像头驱动程序有问题。 小编为你整理了摄像头错误代码0xA00F4244的解决方法&#…...

MFC消息机制

1.消息映射消息映射是一个将消息和成员函数相互关联的表。比如&#xff0c;框架窗口接收到一个鼠标左击消息&#xff0c;MFC将搜索该窗口的消息映射&#xff0c;如果存在一个处理WM_LBUTTTONDOWN消息的处理程序&#xff0c;然后就调用OnButtonDown。2.消息映射机制2.1 声明宏 写…...

全国计算机等级考试报名照片要求以及证件照制作教程

马上就全国计算机等级考试就要开始了&#xff0c;相信现在很多同学都在网上进行报名呢&#xff0c;报名的时候肯定需要用到个人证件照片&#xff0c;所以问题来了&#xff0c;我们怎么自己制作证件照片呢&#xff1f;计算机等级考试报名时对证件照都有哪些要求呢&#xff1f;该…...

SQLSERVER 临时表和表变量到底有什么区别?

一&#xff1a;背景 1. 讲故事 今天和大家聊一套面试中经常被问到的高频题&#xff0c;对&#xff0c;就是 临时表 和 表变量 这俩玩意&#xff0c;如果有朋友在面试中回答的不好&#xff0c;可以尝试看下这篇能不能帮你成功迈过。 二&#xff1a;到底有什么区别 1. 前置思…...

技术生态异军突起,昇思MindSpore进入AI框架第一梯队

ChatGPT掀起的新一轮人工智能狂欢下&#xff0c;隐藏在背后的“大模型”正进入越来越多开发者的视野。 诚如几年前开始流行的一种说法&#xff1a;数据是燃料、模型是引擎、算力是加速器。ChatGPT的出现&#xff0c;恰如其分地诠释了数据、模型和算力的“化学反应”。而在其中…...

审批流、工作流、业务流

是业务流、工作流、审批流 业务流&#xff1a;即业务流程&#xff0c;指为了完成某项业务而进行的各种工作的有序组合 工作流&#xff1a;即工作流程&#xff0c;指为了完成某项工作而进行的各种动作的有序组合 审批流&#xff1a;即审批流程&#xff0c;是对某项工作的审批活动…...

如何利用知识库加强内部管理?

许多公司都知道需要有一个面向客户的知识库&#xff0c;以加强客户服务&#xff0c;提供更好的客户体验。 但是很多企业没有意识到的是&#xff0c;拥有一个内部知识库软件对于员工改善沟通和促进知识共享的重要性。 协作是组织成功的关键部分&#xff0c;通过明确的远景和使…...

饕餮 NFT 作品集来袭!

饕餮 NFT 作品集包含 Chili Game 创作的体验《饕餮》第一章中的角色。可以在 The Sandbox 农历新年活动期间&#xff08;01/18/23 至 02/28/23&#xff09;体验。 饕餮的故事植根于中国古代神话&#xff0c;主要灵感来自《山海经》&#xff0c;一个关于捉妖人「青蛙侠」的故事。…...

C++中的内存分区、引用、函数

内存分区模型 代码区 存放CPU执行的机器指令代码区是共享的且具有只读性 全局区 全局变量和静态变量都存放在此处全局区还包括了常量区、字符串常量和其他常量也存放在此该区域的数据在程序结束后由操作系统释放const修饰的局部变量并不算在全局区 栈区 由编译器自动分配和释放…...

关于angular表格total模板中一直为0

哈喽 小伙伴们大家好昨天在用angular得antdesign组件得table表格 我用total模板 结果&#xff0c;total一直为0这可是愁坏我了 <ng-template #totalTemplate let-total>找到 {{ total }} 条结果</ng-template>[nzShowTotal]"totalTemplate"最后找到原因了…...

多线程事务怎么回滚

背景介绍1&#xff0c;最近有一个大数据量插入的操作入库的业务场景&#xff0c;需要先做一些其他修改操作&#xff0c;然后在执行插入操作&#xff0c;由于插入数据可能会很多&#xff0c;用到多线程去拆分数据并行处理来提高响应时间&#xff0c;如果有一个线程执行失败&…...

基于FPGA的时间数字转换(TDC)设计(五:基于Carry4的高精度TDC设计)

1.基于Carry4进位链设计原理 常见的基于FPGA开发的TDC有直接计数法,多相位时钟采样法,抽头延迟线法等,之前内容为基于多相位的TDC,本章节中,主要讲解基于抽头延迟线法。在Xilinx FPGA开发中,实现抽头延迟线法有很多种,如使用IODELAY构建延迟进位链,此处将介绍基于Carr…...

【C++】二叉搜索树的实现(递归和非递归实现)

文章目录1、二叉搜索树1.1 构建二叉搜索树1.2 二叉搜索树的插入1.3 二叉搜索树的删除1.4 二叉搜索树插入和删除的递归实现为了学习map和set的底层实现&#xff0c;需要知道红黑树&#xff0c;知道红黑树之前需要知道AVL树。 红黑树和AVL树都用到了二叉搜索树结构&#xff0c;所…...

春招来了,如何正确使用领英超高效招聘海外员工、挖掘人才?

金三银四到了&#xff0c;每年的这个时候都是企业招聘的好时机。而领英是目前全球最大的职场社交网络平台&#xff0c;基本上海外求职都是在使用它&#xff0c;所以很多企业涉及到海外招聘时&#xff0c;都会优先考虑领英&#xff0c;但是却经常缺乏一些经验技巧&#xff0c;今…...

Mysql中锁机制深入理解

Mysql中锁机制深入理解默认大家已经知道。分类性能悲观锁&#xff0c;乐观锁操作类型读锁&#xff0c;写锁&#xff0c;数据粒度表锁&#xff0c;行锁&#xff0c;页面锁更细粒度间隙锁&#xff0c;临键锁按使用来讲。由数据粒度出发。表锁&#xff0c;分为 共享锁&#xff0c;…...

去中心化社交网络协议除了Nostr还有哪些?

当下最火的去中心化社交软件Dmaus就是基于Nostr协议开发的&#xff0c;Nostr协议的基本情况之前的文章《一文了解去中心化社交网络协议Nostr》已经做了详细介绍&#xff0c;本文将介绍其他几个目前比较流行的去中心化社交协议。FarcasterFarcaster是由前Coinbase高管Dan Romero…...

【FT2000/4+X100】调试记录

订阅专栏 硬件环境FT2000/4+X100,单板结构,对外显示,运行银行麒麟操作系统。 一 生成UEFI.BIN,烧写在FT2000-4的QSPI Flash中 1 2 下载源文件 edk2-for-support.tar; 参考文件 ft2004c&D2000编译打包说明V1.0.5; 解压源文件; 根目录下 build2004C.sh为四核产品…...

我的Android启动优化—【黑白屏优化】

简述 在Android App使用过程中&#xff0c;对于应用的优化是一个加分项&#xff0c;举个例子&#xff0c;打开你的App需要2秒&#xff0c;人家0.5秒&#xff0c;这就是很大的用户体验上的优化。 问题的产生 在开发中&#xff0c;我们在启动app的时候&#xff0c;屏幕会出现一…...

Linux应用开发之网络套接字编程(实例篇)

服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …...

练习(含atoi的模拟实现,自定义类型等练习)

一、结构体大小的计算及位段 &#xff08;结构体大小计算及位段 详解请看&#xff1a;自定义类型&#xff1a;结构体进阶-CSDN博客&#xff09; 1.在32位系统环境&#xff0c;编译选项为4字节对齐&#xff0c;那么sizeof(A)和sizeof(B)是多少&#xff1f; #pragma pack(4)st…...

从深圳崛起的“机器之眼”:赴港乐动机器人的万亿赛道赶考路

进入2025年以来&#xff0c;尽管围绕人形机器人、具身智能等机器人赛道的质疑声不断&#xff0c;但全球市场热度依然高涨&#xff0c;入局者持续增加。 以国内市场为例&#xff0c;天眼查专业版数据显示&#xff0c;截至5月底&#xff0c;我国现存在业、存续状态的机器人相关企…...

Rapidio门铃消息FIFO溢出机制

关于RapidIO门铃消息FIFO的溢出机制及其与中断抖动的关系&#xff0c;以下是深入解析&#xff1a; 门铃FIFO溢出的本质 在RapidIO系统中&#xff0c;门铃消息FIFO是硬件控制器内部的缓冲区&#xff0c;用于临时存储接收到的门铃消息&#xff08;Doorbell Message&#xff09;。…...

让回归模型不再被异常值“带跑偏“,MSE和Cauchy损失函数在噪声数据环境下的实战对比

在机器学习的回归分析中&#xff0c;损失函数的选择对模型性能具有决定性影响。均方误差&#xff08;MSE&#xff09;作为经典的损失函数&#xff0c;在处理干净数据时表现优异&#xff0c;但在面对包含异常值的噪声数据时&#xff0c;其对大误差的二次惩罚机制往往导致模型参数…...

智能AI电话机器人系统的识别能力现状与发展水平

一、引言 随着人工智能技术的飞速发展&#xff0c;AI电话机器人系统已经从简单的自动应答工具演变为具备复杂交互能力的智能助手。这类系统结合了语音识别、自然语言处理、情感计算和机器学习等多项前沿技术&#xff0c;在客户服务、营销推广、信息查询等领域发挥着越来越重要…...

现有的 Redis 分布式锁库(如 Redisson)提供了哪些便利?

现有的 Redis 分布式锁库&#xff08;如 Redisson&#xff09;相比于开发者自己基于 Redis 命令&#xff08;如 SETNX, EXPIRE, DEL&#xff09;手动实现分布式锁&#xff0c;提供了巨大的便利性和健壮性。主要体现在以下几个方面&#xff1a; 原子性保证 (Atomicity)&#xff…...

Java求职者面试指南:计算机基础与源码原理深度解析

Java求职者面试指南&#xff1a;计算机基础与源码原理深度解析 第一轮提问&#xff1a;基础概念问题 1. 请解释什么是进程和线程的区别&#xff1f; 面试官&#xff1a;进程是程序的一次执行过程&#xff0c;是系统进行资源分配和调度的基本单位&#xff1b;而线程是进程中的…...

08. C#入门系列【类的基本概念】:开启编程世界的奇妙冒险

C#入门系列【类的基本概念】&#xff1a;开启编程世界的奇妙冒险 嘿&#xff0c;各位编程小白探险家&#xff01;欢迎来到 C# 的奇幻大陆&#xff01;今天咱们要深入探索这片大陆上至关重要的 “建筑”—— 类&#xff01;别害怕&#xff0c;跟着我&#xff0c;保准让你轻松搞…...

【学习笔记】erase 删除顺序迭代器后迭代器失效的解决方案

目录 使用 erase 返回值继续迭代使用索引进行遍历 我们知道类似 vector 的顺序迭代器被删除后&#xff0c;迭代器会失效&#xff0c;因为顺序迭代器在内存中是连续存储的&#xff0c;元素删除后&#xff0c;后续元素会前移。 但一些场景中&#xff0c;我们又需要在执行删除操作…...