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

Android之Handler原理解析与问题分享

一、Handler运行原理剖析

1.关系剖析图

如果把整个Handler交互看做一个工厂,Thread就是动力MessageQueue是履带Looper是转轴Loooper的loop方法就是开关,当调用loop方法时整个工厂开始循环工作,处理来自send和post提交到MessageQueue的消息,每处理完一个后由Handler的dispatch分发出去

2.代码走向剖析图

以上代码走向图无论send还是post,最终都是通过Handler的enqueueMessage方法将消息放到MessageQueue中,线程调用loop方法后循环从MessageQueue的next方法中获取消息并进行处理,每处理完一个后由Handler的dispatchMessage分发再通过handleMessage方法回调出去

二、Handler常见问题解答


1.一个线程可以有多少Handler?


无数个,因为在任何地方都可以直接new

2.一个线程可以有几个Looper?你如何保证只有那么多个?


一个,因为源码中已经做了这种判断,在线程被创建时源码中会通过ThreadLocal进行线程与Looper的绑定,通过一个Object[]使前者为key后者为value依次向后,当我们在调用Looper的prepare方法去创建其时,源码中会去调用ThreadLocal的get去判断,如存在抛出异常,不存在则调用set进行创建绑定;如果是主线程,则源码已经在ActivityThread的main方法中为我们创建好了,所以我们可以直接在主线程中new和使用,子线程中却需要调用prepare和loop进行使用

3.Handler为什么会发生内存泄漏?为什么其他的内部类没有这个问题?


因为Java虚拟机中内部类默认持有外部类的引用,当Activity如果在无感知的情况下被销毁时,Handler如果还在执行某些耗时操作时,所以就会产生内存泄漏;这跟Handler的原理有关,因为源码中消息池每一个Message都持有一个target(Handler)对象,而这个target(Handler)对象都持有外部类的引用如Activity,所以其他内部类没有这个问题
拓展:可以通过static+weak reference或Handler的remove对应方法解决

4.为何主线程可以直接new Handler?如果子线程想要new Handler需要做些什么?


因为主线程在ActivityThread的main方法中已经创建了Looper,所以主线程使用Handler时可以直接new;子线程使用Handler时需要调用Looper的prepare和loop方法才能进行使用,否则会抛出异常

5.如果子线程中需要维护一个Looper,当消息队列中没有消息时会发生什么问题?怎么解决?这样解决有什么作用?


当子线程run方法体的业务逻辑执行完时会走到loop处,导致子线程死锁;可以通过调用Looper提供的quitSafely方法,最终调用MessageQueue的quit方法,传一个true即可,如false则抛出异常,感兴趣的小伙伴可以去看看源码,提示主线程不允许退出;作用是移除所有没有处理的消息然后唤醒native锁并且释放资源

6.如果存在多个Handler往MessageQueue中添加数据,因为发送消息时各个Handler可能处于不同的线程,那源码内部是如何实现线程安全的?


因为在源码中可以发现MessageQueue的enqueueMessage方法在将消息推入时将入了同步代码块,在next去消息时也加入了同步代码块,所以保证了Handler消息的通讯是线程安全的

7.我们使用Message时应该怎么样去创建它更合理?


使用obtain去创建Message最合理

8.使用Handler的postDelay等延时方法后消息队列会有什么变化?


会根据delay时间去进行一个时间排序,通过遍历单链表把delay消息插入到合适的位置,然后通过nativePollOnce进行休眠,如有新消息进入则调用nativeWake唤醒,然后再计算时间差进行休眠,直到msg.when >= now为止

9.Looper死循环为什么不会导致应用卡死?


loop循环的取出消息并分发,无消息时会阻塞在next()方法中nativePollOnce()代码行,并释放CPU资源进入休眠,Android的绝大部分操作都是通过Handler机制来完成的,如果没有消息,则不需要程序去响应,就不会发生卡死。应用卡死指的是ANR一般是消息处理过程中耗时太长导致没有及时响应用户的操作

10.源码中是如何对Message做优化的?使用的是什么Java设计模式?


源码中对Message进行了池化策略的优化,避免过多的创建Message对象;享元模式

        

相关文章:

Android之Handler原理解析与问题分享

一、Handler运行原理剖析 1.关系剖析图 如果把整个Handler交互看做一个工厂,Thread就是动力MessageQueue是履带Looper是转轴Loooper的loop方法就是开关,当调用loop方法时整个工厂开始循环工作,处理来自send和post提交到MessageQueue的消息&a…...

YOLO快速入门

Yolo简介 概述 YOLO(You Only Look Once)是一种流行的目标检测算法,由Joseph Redmon等人开发。 YOLO算法以其高效的实时性能和准确的检测能力而闻名。自YOLO的首次提出以来,已经经 历了多个版本的更新和改进。以下是YOLO发展史的…...

基于 LLaMA 和 LangChain 实践本地 AI 知识库

有时候,我难免不由地感慨,真实的人类世界,本就是一个巨大的娱乐圈,即使是在英雄辈出的 IT 行业。数日前,Google 正式对外发布了 Gemini 1.5 Pro,一个建立在 Transformer 和 MoE 架构上的多模态模型。可惜,这个被 Google 寄予厚望的产品并未激起多少水花,因为就在同一天…...

GraphGeo参文2:Fourth-Order Runge–Kutta(四阶RK方法)

四级 RK 方法是数值积分微分方程用的最多的一种方法。 对于形式为: 的微分方程,由如下四级: 若 z 满足: 则有: 其中表示,在时间时,的情况下, 的取值。 其他的类似,括号里…...

解密Lawnchair:打造个性化极致的Android桌面体验

解密Lawnchair:打造个性化极致的Android桌面体验 1. 简介 Lawnchair是一款知名的Android桌面定制工具,旨在为用户提供个性化极致的桌面体验。作为一个开源项目,Lawnchair融合了简洁、灵活和强大的特点,让用户能够自由定制其Andro…...

c语言-函数-009

2.函数传参: 2.1赋值传递&#xff08;复制传递&#xff09;函数体内部想要使用函数体外部变量值的时候使用复制传递2.2全局变量传递#include <stdio.h>int Num1 100; int Num2 200; int Ret 0;void Add(void) {Ret Num1 Num2;return; }int main(void) {Add();printf…...

Spring事件发布监听器ApplicationListener原理- 观察者模式

据说监听器模式也是mq实现的原理, 不过mq我还没来得及深入学习, 先用spring来理解一下吧 Spring事件发布监听器ApplicationListener原理- 观察者模式 什么是观察者模式一个Demo深入认识一下观察者模式Spring中的事件发布监听ps 什么是观察者模式 大家都听过一个故事叫做烽火戏…...

系统学习Python——装饰器:直接管理函数和类

分类目录&#xff1a;《系统学习Python》总目录 在《系统学习Python——装饰器》系列文章中&#xff0c;我们的大多数示例都设计来拦截函数和实例创建调用。这对于装饰器来说很典型&#xff0c;但是它们并不限于这一角色。因为装饰器通过装饰器代码来运行新的函数和类&#xff…...

Leetcode 3049. Earliest Second to Mark Indices II

Leetcode 3049. Earliest Second to Mark Indices II 1. 解题思路2. 代码实现3. 算法优化 题目链接&#xff1a;3049. Earliest Second to Mark Indices II 1. 解题思路 这道题我看貌似难度报表&#xff0c;比赛的时候貌似只有36个人搞定了这道题目&#xff0c;然后最快的人…...

CrossOver 24下载-CrossOver 24 for Mac下载 v24.0.0中文永久版

CrossOver 24是一款可以让mac用户能够自由运行和游戏windows游戏软件的虚拟机类应用&#xff0c;虽然能够虚拟windows但是却并不是一款虚拟机&#xff0c;也不需要重启系统或者启动虚拟机&#xff0c;类似于一种能够让mac系统直接运行windows软件的插件。它以其出色的跨平台兼容…...

算法设计.

文章目录 1. 贪心算法&#xff1a;只看当前1.1 零钱兑换问题&#xff1a;力扣322 2. 活动选择问题3. 动态规划3.1 不同路径&#xff1a;3.2 0-1背包问题3.3 完全背包问题3.4 零钱兑换-动态规划 4. 最长公共字串--动态规划5. 最长公共子序列 1. 贪心算法&#xff1a;只看当前 1…...

20240304金融读报:票据贴现数据挖掘与新质生产力信贷创新

1、【他山之石】票据贴现数据挖掘&#xff1a;邮储三步走&#xff08;为存量科技企业提供贴现、拉国家科技名单拓客、通过贴现激活睡眠对公户、提供不止贴现业务&#xff09; 2、【宏观经济】函数推算的潜在增长率2025之前为4%&#xff0c;2025-2035间为3%。破局在于通过改革、…...

05. Nginx入门-Nginx访问控制

测试环境 此处使用的yum安装的Nginx路径。 此处域名均在本地配置hosts。 主配置文件 路径&#xff1a;/etc/nginx/nginx.conf user nginx; worker_processes auto;error_log /var/log/nginx/error.log notice; pid /var/run/nginx.pid;events {worker_connection…...

S2---FPGA-A7板级原理图硬件实战

视频链接 FPGA-A7板级系统硬件实战01_哔哩哔哩_bilibili FPGA-A7板级原理图硬件实战 基于XC7A100TFGG484的FPGA硬件设计流程图 A7核心板&#xff0c;是基于XILINX公司的ARTIX-7系列100T的XC7A100T,2FGG484I这款芯片开发的高性能核心板&#xff0c;具有高速&#xff0c;高带宽&a…...

RK DVP NVP6158配置 学习

NVP6158简介 NVP6158C是一款4通道通用RX&#xff0c;提供高质量图像的芯片。它接受来自摄像机和其他视频信号的独立4通道通用输入来源。它将4通道通用1M至8M 7.5P视频格式数字化并解码为代表8位ITU-R BT.656/1120 4:2:2格式的数字分量视频&#xff0c;并将单独的BT.601格式与27…...

C++基础2:C++基本数据类型和控制结构

此专栏为移动机器人知识体系下的编程语言中的 C {\rm C} C从入门到深入的专栏&#xff0c;参考书籍&#xff1a;《深入浅出 C {\rm C} C》(马晓锐)和《从 C {\rm C} C到 C {\rm C} C精通面向对象编程》(曾凡锋等)。 2.C基本数据类型和控制结构 2.1 C基本数据类型 程序是由算法…...

HFSS仿真双频微带天线学习笔记

HFSS仿真双频微带天线 文章目录 HFSS仿真双频微带天线1、 求解器设置2、 建模3、 激励方式设置4、 边界条件设置5、 扫频设置6、 设计检查&#xff0c;仿真分析7、 数据后处理 这里重点关注HFSS软件的操作&#xff0c;关于理论知识将在后面的文章中进行更新。 设计要求&#xf…...

【十一】【SQL】外连接(左外连接,右外连接)

数据库中的外连接&#xff08;Outer Join&#xff09;用于连接两个表&#xff0c;并包括两个表中的匹配行以及左表&#xff08;LEFT JOIN&#xff09;或右表&#xff08;RIGHT JOIN&#xff09;中未匹配的行。外连接分为两种主要类型&#xff1a; 左外连接&#xff08;LEFT OU…...

敏捷开发模型:一种灵活、协作和持续的软件开发方法

敏捷开发模型&#xff1a;一种灵活、协作和持续的软件开发方法 引言 在软件开发领域&#xff0c;随着市场需求的不断变化和技术的迅速发展&#xff0c;传统的瀑布模型逐渐暴露出其局限性。为了应对这些挑战&#xff0c;敏捷开发模型应运而生。敏捷开发模型强调灵活、协作和持…...

软件设计师10--计算机组成与体系结构章节回顾

软件设计师10--计算机组成与体系结构章节回顾 章节重要内容考情分析 章节重要内容 考情分析...

什么是库存周转?如何用进销存系统提高库存周转率?

你可能听说过这样一句话&#xff1a; “利润不是赚出来的&#xff0c;是管出来的。” 尤其是在制造业、批发零售、电商这类“货堆成山”的行业&#xff0c;很多企业看着销售不错&#xff0c;账上却没钱、利润也不见了&#xff0c;一翻库存才发现&#xff1a; 一堆卖不动的旧货…...

令牌桶 滑动窗口->限流 分布式信号量->限并发的原理 lua脚本分析介绍

文章目录 前言限流限制并发的实际理解限流令牌桶代码实现结果分析令牌桶lua的模拟实现原理总结&#xff1a; 滑动窗口代码实现结果分析lua脚本原理解析 限并发分布式信号量代码实现结果分析lua脚本实现原理 双注解去实现限流 并发结果分析&#xff1a; 实际业务去理解体会统一注…...

ardupilot 开发环境eclipse 中import 缺少C++

目录 文章目录 目录摘要1.修复过程摘要 本节主要解决ardupilot 开发环境eclipse 中import 缺少C++,无法导入ardupilot代码,会引起查看不方便的问题。如下图所示 1.修复过程 0.安装ubuntu 软件中自带的eclipse 1.打开eclipse—Help—install new software 2.在 Work with中…...

【RockeMQ】第2节|RocketMQ快速实战以及核⼼概念详解(二)

升级Dledger高可用集群 一、主从架构的不足与Dledger的定位 主从架构缺陷 数据备份依赖Slave节点&#xff0c;但无自动故障转移能力&#xff0c;Master宕机后需人工切换&#xff0c;期间消息可能无法读取。Slave仅存储数据&#xff0c;无法主动升级为Master响应请求&#xff…...

使用Matplotlib创建炫酷的3D散点图:数据可视化的新维度

文章目录 基础实现代码代码解析进阶技巧1. 自定义点的大小和颜色2. 添加图例和样式美化3. 真实数据应用示例实用技巧与注意事项完整示例(带样式)应用场景在数据科学和可视化领域,三维图形能为我们提供更丰富的数据洞察。本文将手把手教你如何使用Python的Matplotlib库创建引…...

AirSim/Cosys-AirSim 游戏开发(四)外部固定位置监控相机

这个博客介绍了如何通过 settings.json 文件添加一个无人机外的 固定位置监控相机&#xff0c;因为在使用过程中发现 Airsim 对外部监控相机的描述模糊&#xff0c;而 Cosys-Airsim 在官方文档中没有提供外部监控相机设置&#xff0c;最后在源码示例中找到了&#xff0c;所以感…...

深入理解Optional:处理空指针异常

1. 使用Optional处理可能为空的集合 在Java开发中&#xff0c;集合判空是一个常见但容易出错的场景。传统方式虽然可行&#xff0c;但存在一些潜在问题&#xff1a; // 传统判空方式 if (!CollectionUtils.isEmpty(userInfoList)) {for (UserInfo userInfo : userInfoList) {…...

redis和redission的区别

Redis 和 Redisson 是两个密切相关但又本质不同的技术&#xff0c;它们扮演着完全不同的角色&#xff1a; Redis: 内存数据库/数据结构存储 本质&#xff1a; 它是一个开源的、高性能的、基于内存的 键值存储数据库。它也可以将数据持久化到磁盘。 核心功能&#xff1a; 提供丰…...

消息队列系统设计与实践全解析

文章目录 &#x1f680; 消息队列系统设计与实践全解析&#x1f50d; 一、消息队列选型1.1 业务场景匹配矩阵1.2 吞吐量/延迟/可靠性权衡&#x1f4a1; 权衡决策框架 1.3 运维复杂度评估&#x1f527; 运维成本降低策略 &#x1f3d7;️ 二、典型架构设计2.1 分布式事务最终一致…...

Tauri2学习笔记

教程地址&#xff1a;https://www.bilibili.com/video/BV1Ca411N7mF?spm_id_from333.788.player.switch&vd_source707ec8983cc32e6e065d5496a7f79ee6 官方指引&#xff1a;https://tauri.app/zh-cn/start/ 目前Tauri2的教程视频不多&#xff0c;我按照Tauri1的教程来学习&…...