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

Andrid异步更新UI:Handler(二)深入了解:Message你真的会创建?它是如何子线程和主线程通知?

目录

  1. 为什么会有Handler
  2. Handler的原理,以及对象讲解
  3. 主线程的loop在哪里,为什么主线程loop没有阻塞呢?
  4. Looper如何保证唯一
  5. Handler为什么会引发内存泄漏呢?
  6. Message应该如何创建它?


一、为什么会有Handler


线程分为主线程(主线程又叫UI线程)和子线程,主线程即ActivityThread,规定只有此线程能操作UI,但我们从后台请求数据,都是在子线程操作,所以需要有人帮忙把线程切换一下,所以就有了Handler。


二、Handler的原理,以及对象讲解


2.1 它是如何子线程和主线程通知?

我们来看看Handler的最最最初的实现。主线程和子线程,子线程的数据需要通知到主线程去,主线程拿到数据以后,就去调用方法去更新UI。那么我们想想,如果你去实现子线程通知主线程,也就是两个线程之间通讯,那么你会使用什么方法?

在这里插入图片描述

使用全局变量!共享成员,比如:

//这里只是简单的介绍了一下
var flag:Boolean = false
Thread(object :Runnable{override fun run() {if (flag) {//调用通知UI更新的方法}}}).start()Thread(object :Runnable{override fun run() {flag = true}}).start()

如下,sendMessage就是上面的一个变化通知,当收到新消息的时候,则会回调handleMessage方法进行操作。

	
handler.sendMessage(uimsg);final Handler handler = new Handler() {@Overridepublic void handleMessage(Message msg) {getMessage(msg);}
};

2.2 对象讲解:looper,message,messagequeue

Handler当然没有我们上面说的那么简单,只是我们拆开了最初的原理。接下来我们再讲一下Looper对象,我们可以注意到,我们写的最初的线程,执行完就结束了,那么肯定不能结束呀,对吧,因为他要继续监听消息。所以呢,还应该进行如下这样的改进,让它不断的循环:

var flag:Boolean = falseThread(object :Runnable{override fun run() {while (run){if (flag) {//调用通知UI更新的方法}}}}).start()Thread(object :Runnable{override fun run() {flag = true}}).start()

而对应到Handler,Looper就是做这个事情的,我们可以看看源码就会有一个循环,不断的循环处理消息:
在这里插入图片描述因为消息很多(message),所以我们会有一个MessageQueue通道来进行管理、传输以及通知。

消息来了以后,loop收到以后开始发送,loop有一个for循环的功能。这里注意一个问题,loop是已经开始运转了,还是收到消息才开始启动呢?

在这里插入图片描述

没错,是已经运转了。线程一开启,就立马启动了。上面的例子我们可以看到,for已经循环了。

我们可以看看调用handleMessage的源码:
在这里插入图片描述looper在循环,如果有数据则开始调用回调,而通知的方法则在handler里面。

在这里插入图片描述源码的主要方法调用:
在这里插入图片描述
流程示意图:
在这里插入图片描述

2.3 这里有一个疑问,loop是如何知道线程是谁的,queue又是谁的

直接在handler里面创建了looper,所以就知道是谁的了。
在这里插入图片描述而queue则是在looper里面创建的。

在这里插入图片描述


三、主线程的loop在哪里,为什么主线程loop没有阻塞呢?


主线程的loop在哪里,在main方法,ActivityThread里面:

在这里插入图片描述

在这里插入图片描述我们可以注意到,主线程也不会结束,mian方法也有一个loop循环。

在这里插入图片描述
为什么主线程loop没有阻塞呢?但我们看到,其实他还是阻塞的,不阻塞,程序就运行完成了。只不过,他是如何阻塞的?他是有数据刷新才运行,没有数据刷新就阻塞,让出cpu,所以他采用的队列、epoll阻塞,去执行其他的任务,比如刷新ui。



四、Looper如何保证唯一


一个线程只能有一个loop,不可能有多个,因为你调用了looper的loop,后面的代码就不会执行了。
调用两次prepare会崩溃,为什么会崩溃呢?因为一个线程只能有一个looper,源码里面直接报错了:
在这里插入图片描述在这里插入图片描述判断有没有值。有,直接报错,没有就往下执行。这就是它的执行方式。
在这里插入图片描述


五、Handler为什么会引发内存泄漏呢?


Handler是内部类,内部类持有外部类的引用。但为什么其他内部类就可以呢?持有链。长生命周期,持有短生命周期的引用,就会导致无法被释放。

5.1 持有链

首先我们先想想,哪个对象不可能被释放?

在这里插入图片描述

没错,主线程对象。然后主线程对象持有looper,而looper持有messagequeue,而messagequeue持有message,message是一个链表,而message又持有hander,而handler又持有activity,所以长生命周期持有短生命周期activity,那么页面切换,activity就无法得到释放。

在这里插入图片描述在这里插入图片描述

六、Message应该如何创建它?


在这里插入图片描述为什么用2呢?这里要了解一下内存抖动。用第一种,会导致创建大量的对象并销毁对象就是内存抖动。如下这种就是内存抖动。
在这里插入图片描述
解决内存抖动的根本方法,就是内存复用,对象复用。所以我们要调用obtain方法。message是一个链表,存储着message进行复用。
在这里插入图片描述
这里的spool就是一个message。如果你直接new message,那么每次都是一个新的链表,而使用Message的obtain方法,它会进行复用。

相关文章:

Andrid异步更新UI:Handler(二)深入了解:Message你真的会创建?它是如何子线程和主线程通知?

目录 为什么会有HandlerHandler的原理,以及对象讲解主线程的loop在哪里,为什么主线程loop没有阻塞呢?Looper如何保证唯一Handler为什么会引发内存泄漏呢?Message应该如何创建它? 一、为什么会有Handler 线程分为主线…...

2025计算机毕设50条小众好做的Java题目【计算机毕设选题推荐】

随着2025年的到来,计算机专业的学生们又迎来了毕业设计的关键时刻。对于大多数学生来说,选择一个合适的毕业设计题目往往是一项艰巨的任务。本文旨在为那些正在为毕业设计题目烦恼的同学们提供一些灵感和建议,特别是针对使用Java技术栈的同学…...

day06_算法训练

一. Stream流 1.1 Stream流概述 概念: jdk1.8以后提供的新的API, 主要用于批量操作数据(集合的另外一种操作方式),代码非常简洁 流式处理思想: 2.2 Stream对象获取 1.单列集合的Stream流对象获取 2.双列集合的Stream流对象获取 3.数组的Stream流对象获取 4.散装数据的St…...

@SpringBootTest单元测试中报错:无法自动装配,找不到 ‘XXX‘ 类型的 Bean

一开始照着网上教程讲Springboot原理中的代码来copy写的↓ import com.google.gson.Gson; import com.itheima.pojo.Result; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.cont…...

nodemon学习(一)简介、安装、配置、使用

nodemon用来监视node.js应用程序中的任何更改并自动重启服务,非常适合用在开发环境中。以前,我们开发一个node后端服务时,每次更改文件,均需重启一下,服务才能生效。这使我们的开发效率降低了很多。nodemon的出现,可以…...

【Qt从摄像头视频中获取数据】

有时候需要在视频上画图,所以需要能获取到每一帧视频数据。 以前从视频文件或视频流中得到帧,一般都是使用qt ffmpeg或qt vlc。 qt对显示处理视频大体有以下方法: QMediaPlayer QVideoWidget 这种方法只适合简单的显示视频功能&#xff…...

视频截取中的UI小组件

引言 视频截取在社交类 APP 中十分常见。有了上传视频的功能,就不可避免地需要提供截取和编辑的选项。如果我们过度依赖第三方库,项目的代码可能会变得异常臃肿,因为这些库往往包含许多我们用不到的功能,而且它们的 UI 样式和功能…...

java设计模式--结构型模式

结构性模式:适配器模式、桥接模式、装饰模式、组合模式、外观模式、享元模式、代理模式 适配器模式 适配器模式(Adapter Pattern) 充当两个不兼容接口之间的桥梁,属于结构型设计模式。目的是将一个类的接口转换为另一个接口&am…...

消息中间件:Kafka消息丢失与堆积问题分析与解决方案

消息中间件:Kafka消息丢失与堆积问题分析与解决方案 Kafka作为分布式消息系统,广泛应用于实时数据流处理、大数据分析等领域。然而,在实际应用中,Kafka可能会面临消息丢失和消息堆积的问题,这些问题如果得不到有效处理…...

mac终端代理配置指南

终端代理配置指南 在 macOS 中,你可以通过几种不同的方法来配置终端代理。这里介绍两种常见的设置方式:使用 alias 和 shell 函数。 方法 1:使用 Alias 配置代理 打开终端配置文件 默认情况下,macOS 终端使用的是 zsh。如果你的系…...

mbedTLS生成客户端,服务端密钥及CA证书

1. mbedTLS源码:https://github.com/Mbed-TLS/mbedtls.git 2. 生成步骤: 2.1 编译上述源码 2.2 生成CA私钥和自签名证书: 进入编译的build目录,比如:/mbedtls-development/build# 2.2.1生成CA私钥 执行下面的命令&…...

如何有效应对突发技术故障:以网易云音乐为例

引言 在互联网行业,任何一个在线服务都可能遭遇突发的技术故障。这些故障不仅影响用户体验,还可能对公司的品牌形象造成损害。因此,如何快速响应并高效解决这些问题成为了每一个开发团队的重要课题。本文将以网易云音乐在2024年8月19日下午遭…...

上传文件到github仓库

REF: https://blog.csdn.net/litianxiang_kaola/article/details/74075151 已有repository,往仓库里更新内容 点击gitlab里的clone 在git bash中使用git clone,这个时候会将网上的仓库下载到本地,你可以把想要更新的内容直接拖到仓库里 …...

clip-path实现图片边角的裁剪

img {clip-path: polygon(0 7px,7px 0,calc(100% - 20px) 0,100% 20px,100% 100%,16px 100%,0 calc(100% - 16px));}每一个逗号隔开的就是路径坐标 左上角的两个点 0 7px ,7px 0 右上角 calc(100% - 20px) 0,100% 20px 相当于通过这些点练成的线的圈起来的部分就是剩…...

【C++ Primer Plus习题】2.7

问题: 解答: #include <iostream> using namespace std;void print(int hour, int minute) {cout << "Time:" << hour << ":" << minute << endl; }int main() {int hour0;int minute 0;cout << "请输入…...

uboot中 fastboot udp 协议分析

注&#xff1a; 1. 本文所分析的fastboot源码不是android下的源码&#xff0c;而是恩智浦芯片厂商在IMX6UL芯片的uboot源码中自己实现的源码&#xff0c;二者不同&#xff0c;请读者注意区分。一些图片是网上找到的&#xff0c;出处不好注明&#xff0c;请见谅。 2. 分析fastbo…...

redis hash类型的命令

1.hset 格式&#xff1a; hset key field value [field value ...]&#xff08;value是字符串&#xff09; 返回值&#xff1a;设置成功的键值对的个数 2.hget&#xff1a;获取键值对 格式:hget key field 3.hexists&#xff1a;判断hash中是否存在指定 格式&#xff1a;…...

【OpenCV】 中使用 Lucas-Kanade 光流进行对象跟踪和路径映射

文章目录 一、说明二、什么是Lucas-Kanade 方法三、Lucas-Kanade 原理四、代码实现4.1 第 1 步&#xff1a;用户在第一帧绘制一个矩形4.2 第 2 步&#xff1a;从图像中提取关键点4.3 第 3 步&#xff1a;跟踪每一帧的关键点 一、说明 本文针对基于光流法的目标追踪进行叙述&am…...

ES 支持乐观锁吗?如何实现的?

本篇主要介绍一下Elasticsearch的并发控制和乐观锁的实现原理&#xff0c;列举常见的电商场景&#xff0c;关系型数据库的并发控制、ES的并发控制实践。 并发场景 不论是关系型数据库的应用&#xff0c;还是使用Elasticsearch做搜索加速的场景&#xff0c;只要有数据更新&…...

前端宝典十一:前端工程化稳定性方案

一、工程化体系介绍 1、什么是前端工程化 前端工程化 前端 软件工程&#xff1b;前端工程化 将工程方法系统化地应用到前端开发中&#xff1b;前端工程化 系统、严谨、可量化的方法开发、运营和维护前端应用程序&#xff1b;前端工程化 基于业务诉求&#xff0c;梳理出最…...

yum 数据源的切换

本来准备安装一个ntp 服务器时间进行同步&#xff0c;但是使用yum install ntp -y 但是却失败了 原因是yum自带的镜像源不能用了&#xff0c;所以要想使用yum 多功能只能切换yum 对应的镜像源了 如果你的服务商是可以使用wget命令的&#xff1a; wget -O /etc/yum.repos.d/Ce…...

MySQL入门学习-命令行工具.mysqlbinlog

MySQL 命令行工具mysqlbinlog用于处理二进制日志文件。 一、关于mysqlbinlog工具的详细介绍&#xff1a; 1、命令行工具mysqlbinlog的特点和使用方法&#xff1a; - 特点&#xff1a; - 可以解析和查看二进制日志文件的内容。 - 支持多种输出格式&#xff0c;如文本、SQ…...

WARNING XXX is not overriding the create method in batch

WARNING XXX is not overriding the create method in batch api.modeldef create(self, vals):quvals[name]youqu self.env[crm.qu].sudo().search([(name, , qu),(shi_id,,vals[shi_id])])if len(youqu)>0:raise UserError(_("该区名已存在&#xff0c;无需再填加…...

使用预训练的 ONNX 格式的目标检测模型(基于 YOLOv8n-pose)姿态监测

具体步骤如下&#xff1a; 加载图像&#xff1a; 从指定路径读取一张图像&#xff08;这里假设图像名为bus.jpg&#xff09;。将图像从 BGR 颜色空间转换为 RGB 颜色空间。 图像预处理&#xff1a; 计算图像的高度、宽度&#xff0c;并确定其中的最大值作为新图像的边长。创建一…...

matlab实现模拟退火算法

模拟退火算法&#xff08;Simulated Annealing, SA&#xff09;是一种通用概率优化算法&#xff0c;用于在给定的大搜索空间内寻找问题的近似全局最优解。该算法灵感来源于物理学中固体物质的退火过程&#xff0c;其中温度逐渐降低&#xff0c;粒子逐渐趋于能量最低状态。 在M…...

【Prettier】代码格式化工具Prettier的使用和配置介绍

前言 前段时间&#xff0c;因为项目的prettier的配置和eslint格式检查有些冲突&#xff0c;在其prettier官网和百度了一些配置相关的资料&#xff0c;在此做一些总结&#xff0c;以备不时之需。 Prettier官网 Prettier Prettier 是一种前端代码格式化工具&#xff0c;支持ja…...

【计算机网络】网络基础

&#x1f466;个人主页&#xff1a;Weraphael ✍&#x1f3fb;作者简介&#xff1a;目前正在学习c和算法 ✈️专栏&#xff1a;Linux &#x1f40b; 希望大家多多支持&#xff0c;咱一起进步&#xff01;&#x1f601; 如果文章有啥瑕疵&#xff0c;希望大佬指点一二 如果文章对…...

MFC在对话框中实现打印和打印预览

首先在这里感谢互联网的大哥们&#xff01;同时我讨厌动不动就是要vip才能查看&#xff01;所以我写的不需要vip就能看。只求点个赞。 直接上代码&#xff0c;新建6个文件CPrintFrame.cpp&#xff1b;CPrintFrame.h&#xff1b;CPrintPreviewView.cpp&#xff1b;CPrintPrevie…...

移动端页面出现闪屏

v-cloak 的作用和用法 用法&#xff1a; 这个指令保持在元素上直到关联实例结束编译。和 CSS 规则如 [v-cloak] { display: none } 一起用时&#xff0c;这个指令可以隐藏未编译的 Mustache 标签直到实例准备完毕。官方API {{msg}} HTML 绑定 Vue实例&#xff0c;在页面加载时…...

elasticsearch的高亮查询三种模式查询及可能存在的问题

目录 高亮查询使用介绍 高亮参数 三种分析器 可能存在的查询问题 fvh查询时出现StringIndexOutOfBoundsException越界 检索高亮不正确 参考文档 高亮查询使用介绍 Elasticsearch 的高亮&#xff08;highlight&#xff09;可以从搜索结果中的一个或多个字段中获取突出显…...