关于Handler你不知道的事

提到Handler,我们都会想到可以用来在子线程给UI线程发送消息,常用来子线程刷新UI。
而往深了问,你一定还知道Handler会绑定到一个Looper,而每个Looper会和一个MessageQ关联,从而达到向指定线程发送消息的功能。除此之外,还了解多少?
提到MessageQueue,就不得不聊到Android的消息处理机制。

Handler消息处理机制

Android的消息机制,涉及到HandlerLooperMessageMessageQueue

  • Handler是用于处理Message的对象。它通常与一个特定的线程(通常是主线程)关联。通过Handler开发者可以将Message发送到与其关联的线程的消息队列中,以便在那个线程中执行处理。
  • Message是一个包含要传递的数据和指令的的对象。当需要在不同线程之间传递数据或执行行任务时,通常会创建一个Message并将其发送给Handler
  • Looper是一个用于管理线程的消息队列别的对象。每个线程都可以有一个Looper,它会在线程上创建一个消息队列,允许该线程接收并处理Message。主线程通常已经具有一个默认的Looper,而其他线程需要显式创建一个Looper
  • MessageQueue即是消息队列。是一个FIFO(先进先出)队列,用于存储待处理的Message。每个Looper都有一个关联的MessageQueueHandlerMessage发送到这个队列中,然后由Looper依次处理队列中的Message

简易的消息处理机制流程图

Developer Looper Handler MessageQueue JNI Looper@prepare 循环取消息 Handler@dispatchMessage Looper@loop Message@next nativePollOnce native处理MessageQ及Looper Message@Callback Handler Handler Message@recycerUnchecked Message@obtain Handler@enqueueMessage MessageQueue@enqueueMessage nativeWake Developer Looper Handler MessageQueue JNI

MessageQueue

从上面的描述,我们可以MessageQueue会按照一定的规则取出要执行的Message,当消息执行完之后Message就会被回收。

那么下面我们就通过代码来验证几种情况:

  • Message#Obtain创建消息的消息和直接New Message的方法创建消息,是否都会被回收
  • 如果消息对象被持有,是否消息也会被回收
  • 如果接受消息在主线程,那么在View#post方法执行后,消息是否会被回收
  • 如果接收消息在主线程,那么当切换到其他线程执行任务后,消息是否会被回收
  • 如果接受消息在主线程,通过Kotlin Coroutine执行任务在 Dispatchers.MainDispatchers.Default后,消息是否会被回收

通过Message#Obtain创建消息并发送

 Message.obtain(). also { it.what = 1  mObtainMsg = it mHandler.sendMessage(it) } 

通过直接New的方法创建消息并发送

Message().also {
it.what = 2mHandler.sendMessage(it)
} 

发送消息后打印消息信息

class MyHandler(private val actRef: WeakReference<TestMessageActivity>) :Handler(Looper.getMainLooper()) {override fun handleMessage(msg: Message) {super.handleMessage(msg)val act = actRef.get() ?: returnLog.d(TAG, "msg:$msg}")Log.d(TAG, "mObtainMsg:${act.mObtainMsg}}")act.mSWThread.post {
Log.d(TAG, "msg--post:$msg}")Log.d(TAG, "mObtainMsg--post:${act.mObtainMsg}}")}
if (act.mSWThread.isChecked) {//是否开启了子线程Thread {
Log.d(TAG, "thread--msg:$msg}")Log.d(TAG, "thread--mObtainMsg:${act.mObtainMsg}}")Thread.sleep(3000L)Log.d(TAG, "threadAfter--msg:$msg}")Log.d(TAG, "threadAfter--mObtainMsg:${act.mObtainMsg}}")} .start()}if (act.mSWCoroutine.isChecked) {//是否开启协程GlobalScope.launch(Dispatchers.Main) {
Log.d(TAG, "launchMain----msg:$msg}")Log.d(TAG, "launchMain--mObtainMsg:${act.mObtainMsg}}")}
GlobalScope.launch {
Log.d(TAG, "launch--msg:$msg}")Log.d(TAG, "launch--mObtainMsg:${act.mObtainMsg}}")}
}}
}

Obtain创建消息发送消息,收到的日志结果

2024-03-22 16:32:04.780 21621-21621/com.lotus.duode.myapplication D/TestMessageActivity: msg:{ when=-1ms what=1 target=com.lotus.duode.myapplication.TestMessageActivity$MyHandler }}
2024-03-22 16:32:04.780 21621-21621/com.lotus.duode.myapplication D/TestMessageActivity: mObtainMsg:{ when=-1ms what=1 target=com.lotus.duode.myapplication.TestMessageActivity$MyHandler }}
2024-03-22 16:32:04.781 21621-22106/com.lotus.duode.myapplication D/TestMessageActivity: thread--msg:{ when=-2ms what=1 target=com.lotus.duode.myapplication.TestMessageActivity$MyHandler }}
2024-03-22 16:32:04.781 21621-22106/com.lotus.duode.myapplication D/TestMessageActivity: thread--mObtainMsg:{ when=-2ms what=1 target=com.lotus.duode.myapplication.TestMessageActivity$MyHandler }}
2024-03-22 16:32:04.803 21621-22108/com.lotus.duode.myapplication D/TestMessageActivity: launch--msg:{ when=-19ms callback=android.view.Choreographer$FrameDisplayEventReceiver target=android.view.Choreographer$FrameHandler }}
2024-03-22 16:32:04.803 21621-22108/com.lotus.duode.myapplication D/TestMessageActivity: launch--mObtainMsg:{ when=-19ms callback=android.view.Choreographer$FrameDisplayEventReceiver target=android.view.Choreographer$FrameHandler }}
2024-03-22 16:32:04.806 21621-21621/com.lotus.duode.myapplication D/TestMessageActivity: msg--post:{ when=-2d2h37m50s923ms barrier=0 }}
2024-03-22 16:32:04.806 21621-21621/com.lotus.duode.myapplication D/TestMessageActivity: mObtainMsg--post:{ when=-2d2h37m50s923ms barrier=0 }}
2024-03-22 16:32:04.806 21621-21621/com.lotus.duode.myapplication D/TestMessageActivity: launchMain----msg:{ when=-2d2h37m50s923ms barrier=0 }}
2024-03-22 16:32:04.806 21621-21621/com.lotus.duode.myapplication D/TestMessageActivity: launchMain--mObtainMsg:{ when=-2d2h37m50s923ms barrier=0 }}
2024-03-22 16:32:07.782 21621-22106/com.lotus.duode.myapplication D/TestMessageActivity: threadAfter--msg:{ when=-2d2h37m53s899ms barrier=0 }}
2024-03-22 16:32:07.782 21621-22106/com.lotus.duode.myapplication D/TestMessageActivity: threadAfter--mObtainMsg:{ when=-2d2h37m53s899ms barrier=0 }}

New Message创建消息发送消息,收到的日志结果

2024-03-22 16:32:27.427 21621-21621/com.lotus.duode.myapplication D/TestMessageActivity: msg:{ when=-9ms what=2 target=com.lotus.duode.myapplication.TestMessageActivity$MyHandler }}
2024-03-22 16:32:27.428 21621-21621/com.lotus.duode.myapplication D/TestMessageActivity: mObtainMsg:{ when=-2ms callback=android.view.Choreographer$FrameDisplayEventReceiver target=android.view.Choreographer$FrameHandler }}
2024-03-22 16:32:27.428 21621-22116/com.lotus.duode.myapplication D/TestMessageActivity: thread--msg:{ when=-10ms what=2 target=com.lotus.duode.myapplication.TestMessageActivity$MyHandler }}
2024-03-22 16:32:27.428 21621-22116/com.lotus.duode.myapplication D/TestMessageActivity: thread--mObtainMsg:{ when=-3ms callback=android.view.Choreographer$FrameDisplayEventReceiver target=android.view.Choreographer$FrameHandler }}
2024-03-22 16:32:27.428 21621-22108/com.lotus.duode.myapplication D/TestMessageActivity: launch--msg:{ when=-2d2h38m13s545ms barrier=0 }}
2024-03-22 16:32:27.428 21621-22108/com.lotus.duode.myapplication D/TestMessageActivity: launch--mObtainMsg:{ when=-3ms callback=android.view.Choreographer$FrameDisplayEventReceiver target=android.view.Choreographer$FrameHandler }}
2024-03-22 16:32:27.430 21621-21621/com.lotus.duode.myapplication D/TestMessageActivity: msg--post:{ when=-1ms callback=android.view.Choreographer$$ExternalSyntheticLambda0 target=android.view.Choreographer$FrameHandler }}
2024-03-22 16:32:27.430 21621-21621/com.lotus.duode.myapplication D/TestMessageActivity: mObtainMsg--post:{ when=-2d2h38m13s547ms barrier=0 }}
2024-03-22 16:32:27.430 21621-21621/com.lotus.duode.myapplication D/TestMessageActivity: launchMain----msg:{ when=-2ms callback=android.view.Choreographer$$ExternalSyntheticLambda0 target=android.view.Choreographer$FrameHandler }}
2024-03-22 16:32:27.430 21621-21621/com.lotus.duode.myapplication D/TestMessageActivity: launchMain--mObtainMsg:{ when=-2d2h38m13s547ms barrier=0 }}
2024-03-22 16:32:30.429 21621-22116/com.lotus.duode.myapplication D/TestMessageActivity: threadAfter--msg:{ when=-2d2h38m16s546ms barrier=0 }}
2024-03-22 16:32:30.429 21621-22116/com.lotus.duode.myapplication D/TestMessageActivity: threadAfter--mObtainMsg:{ when=-2d2h38m16s546ms barrier=0 }}

结论

通过Handler#handleMessage接收的消息,在消息执行完成之后。如果后续有新的消息需要被使用,那么系统会通过Message#obtain创建消息时,就会从Message#sPool 中进行复用

请添加图片描述

而消息的回收是在DispatchMessage完成之后。

在这里插入图片描述

因此如果我们需要持久化使用Message中的信息时,就需要使用变量对这些信息进行存储。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/3281626.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

【计算机视觉学习之CV2图像操作实战:红绿灯识别1】

红绿灯识别1 步骤 高斯模糊边缘提取膨胀腐蚀中值滤波再次膨胀霍夫圆环检测区域将图片从BGR格式转换为HSV格式设计颜色阈值中值滤波统计像素点数 import cv2 import numpy as np COLOERS {red: (0, 0, 255),green: (0, 255, 0),yellow: (0, 255, 255), } def detect_color(im…

探索Netty框架的核心构件

Netty是一个高性能、异步事件驱动的网络应用程序框架&#xff0c;用于快速开发可维护的高性能、高可靠性的网络服务器和客户端程序。本文将深入探讨Netty框架的基本组件&#xff0c;帮助开发者更好地理解和使用这一强大的工具。 1. 事件循环&#xff08;EventLoop&#xff09;…

系统架构师--第1章计算机组成与体系结构-1.2 存储器系统

目录 1.2 存储器系统 1.2.1 主存储器 1.2.2 辅助存储器 1.2.3 Cache 存储器 &#xff08;1&#xff09;直接映像 &#xff08;2&#xff09;全相联映像 &#xff08;3&#xff09;组相联映像 1.2 存储器系统 存储器是用来存放程序和数据的部件&#xff0c;它是一个记忆装…

Vue - CSS基础学习

一、元素及属性 CSS 是为 web 内容添加样式的代码。 style标签 1.语法 1.除了选择器部分&#xff0c;每个规则集都应该包含在成对的大括号里&#xff08;{}&#xff09;。 2.在每个声明里要用冒号&#xff08;:&#xff09;将属性与属性值分隔开。 3.在每个规则集里要用分号…

Android Studio运行报错:module java.base dose not “opens java.io“ to unnamed module

今天第一次使用Android Studio运行一个安卓工程&#xff0c;报如图错误,应该是环境问题。 解决&#xff1a; 右上角的设置图标->settings->Buid,Execution,Deployment->Build Tools->Gradle->Gradle JDK->选择本地环境的java_home jdk&#xff08;怎么安装…

SEQ 4. 转录本蛋白编码能力预测软件(CPAT)

简 介 深度转录组测序能够检测数千个新的转录本。这一发现大而“隐藏”的转录组重新激活了对能够快速区分编码和非编码 RNA 的方法的需求。在这里提出了一种新的无比对方法&#xff0c;编码潜在评估工具( CPAT) &#xff0c;可以快速识别来自大量候选转录本的编码和非编码转…

公司里的IT是什么?

公司里的IT是什么&#xff1f; 文章目录 公司里的IT是什么&#xff1f;1、公司里的IT2、IT技术3、IT行业4、IT行业常见证书 如果对你有帮助&#xff0c;就点赞收藏把&#xff01;(&#xff61;&#xff65;ω&#xff65;&#xff61;)&#xff89;♡ 前段时间&#xff0c;在公…

【C语言】指针基础知识理解【续】

1. ⼆级指针 指针变量也是变量&#xff0c;是变量就有地址&#xff0c;那指针变量的地址存放在哪⾥&#xff1f;这就是 ⼆级指针 。 1.1 引入二级指针 由于一级指针已经很熟悉&#xff0c;这里就不再赘述&#xff0c;这里我们重点探讨二级指针 下面先简单使用一个二级指针看…

TPAMI 2024 | 全新框架!深度学习可解释度量学习!

TPAMI 2024 | 全新框架&#xff01;深度学习可解释度量学习&#xff01; DIML: Deep Interpretable Metric Learning via Structural Matching 题目&#xff1a;DIML: 通过结构匹配的深度可解释度量学习 作者&#xff1a;Wenliang Zhao, Yongming Rao, Jie Zhou , and Jiwen…

C++笔试强训10

文章目录 一、选择题1-5题6-10题 二、编程题题目一题目二 一、选择题 1-5题 前面做过很多次了&#xff0c;记住就好&#xff0c;不在赘述&#xff0c;选C。 内联函数经常使用的场景包括&#xff1a; 小型函数&#xff1a;当函数体非常小&#xff0c;只包含几条语句时&#xf…

【C++】模板的特化

文章目录 概念函数模板特化类模板特化全特化偏特化 概念 通常情况下&#xff0c;使用模板可以实现一些与类型无关的代码&#xff0c;但是有一些类型需要特殊处理&#xff0c;否则可能会得到一些错误的结果。 比如&#xff0c;在比较两个数的大小时&#xff0c;如果传入两个变量…

手动上电电路(电路收藏)

SW1按下 V1栅极对地 V1通 Vout给Mcu工作 GPIO2 高电平 V2通 SW1松开 V1栅极依然通过V2对地 维持V1通 Vout。再次按下SW1 GPIO1 对地 使Mcu收到中断 将GPIO2 输出低电平 V2关 松开SW1 V1栅极悬空 V1断开 Vout被截断

产品思维之什么是好的设计?

点击下方“JavaEdge”&#xff0c;选择“设为星标” 第一时间关注技术干货&#xff01; 免责声明~ 任何文章不要过度深思&#xff01; 万事万物都经不起审视&#xff0c;因为世上没有同样的成长环境&#xff0c;也没有同样的认知水平&#xff0c;更「没有适用于所有人的解决方案…

原生微信小程序wxml2canvas生成海报并包保存至本地

Wxml2Canvas是什么&#xff1f; Wxml2Canvas 是一个用于微信小程序开发的工具库&#xff0c;主要用途是将小程序页面的内容绘制成图片&#xff0c;以便生成海报或保存分享图片到相册等功能。具体用途包括&#xff1a; ①海报生成功能&#xff1a;允许开发者将当前页面的特定部…

【机器学习】决策边界的基本概念以及如何在逻辑回归中找到决策边界

引言 在机器学习中&#xff0c;决策边界是分类算法用来区分不同类别数据点的线、面或超平面。这些边界通常是模型的预测规则&#xff0c;用于将特征空间中的点分配到不同的类别。决策边界可以是线性的&#xff0c;也可以是非线性的&#xff0c;取决于数据的分布和所使用的分类算…

鸿蒙 HarmonyOS NEXT端云一体化开发-云数据库篇

一、概述 云数据库是一款基于对象模型的数据库&#xff0c;采用存储区、对象类型和对象三级结构。 数据模型 存储区 存储区是一个独立的数据存储区域&#xff0c;多个数据存储区之间相互独立&#xff0c;每个存储区拥有完全相同的对象类型定义 --类似于关系型数据库中的da…

ECMA6Script学习笔记(五)

【摘要】 本文是对自己学习ES6的学习笔记回顾,后面是概要: 本文介绍了ES6中的对象创建和拷贝方法。对象创建方面&#xff0c;ES6通过class关键字支持了面向对象的语法糖&#xff0c;包括属性设置、getter和setter方法、构造器、静态方法以及私有属性的定义。同时&#xff0c;展…

专业做护眼灯的有哪些品牌?五款市面主流护眼灯专业测评

专业做护眼灯的有哪些品牌&#xff1f;市面上出现的品牌毫不夸张的说&#xff0c;真的算得上是琳琅满目&#xff0c;而且每一个品牌都在说自己的产品才是最值得的&#xff0c;这种情况下来&#xff0c;很多人一时之间根本就不知道要选择哪一款比较好。而且还有一些还会买到低劣…

vue基础知识总结(2)--- axios的使用

一.下载Vue3&#xff1a; 选择自己想要下载的项目文件夹&#xff0c;cmd回车打开命令栏&#xff0c;执行 &#xff1a; cnpm init vuelatest 然后等待一会就可以创建一个项目&#xff0c;并更改项目名&#xff1a; √ 请输入项目名称&#xff1a; ... vue-project 之后按照…

华为仓颉语言测试申请

1. 申请网址 HarmonyOS NEXT仓颉语言开发者预览版 Beta招募- 华为开发者联盟 点击立即报名登录华为账号 勾选选项 , 点击同意 按要求填写信息即可 2. 申请通过后官方会通过邮件的方式发送相关下载途径 , 根据文档进行下载即可 package Cangmain(): Int64 {println("你…