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对象;享元模式

        

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

08. Nginx进阶-Nginx动静分离

简介 什么是动静分离? 通过中间件将动态请求和静态请求进行分离。分离资源,减少不必要的请求消耗,减少请求延时。 动静分离的好处 动静分离以后,即使动态服务不可用,静态资源仍不受影响。 动静分离示意图 动静分离…

Day16:信息打点-语言框架开发组件FastJsonShiroLog4jSpringBoot等

目录 前置知识 指纹识别-本地工具-GotoScan(CMSEEK) Python-开发框架-Django&Flask PHP-开发框架-ThinkPHP&Laravel&Yii Java-框架组件-Fastjson&Shiro&Solr&Spring 思维导图 章节知识点 Web:语言/CMS/中间件/…

Python的http模块requests

模块简介: requests 库是一个 python中比较有名的 http请求的库,能处理 get,post,put,delete 等 restful请求,能设置 header,cookie,session 等操作,也是作为爬虫的基础库,它目前还不能异步请求,如果要支持…

适用于 Windows 的 5 款最佳免费数据恢复软件榜单

每个计算机用户都曾经历过数据丢失的情况。很容易错误地删除重要的文件和文件夹,当发生这种情况时,可能会导致不必要的心痛和压力。值得庆幸的是,可以恢复 Windows PC 上丢失的数据。在本文中,我们将分享您可以使用的五种最佳 Win…

苹果因在iOS音乐流媒体市场上的反向引导行为,在欧盟被罚款18.4亿欧元

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗?订阅我们的简报,深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同,从行业内部的深度分析和实用指南中受益。不要错过这个机会,成为AI领…

Docker之自定义镜像上传阿里云

目录 一. Alpine制作jdk镜像 1.1 alpine Linux 简介 1.2 基于alpine制作jdk8镜像 1.2.1 下载镜像 1.2.2 创建并编辑Dockerfile 1.2.3 上传文件 1.2.4 执行Dockerfile构建镜像 1.2.5 测试 二. Alpine制作jre镜像 2.1 首先下载jre或者上传 2.2 解压 2.3 测试 2.4 返回上级目录&a…

云手机的境外舆情监控应用——助力品牌公关

在当今数字化时代,社交媒体已成为品牌传播和互动的主要平台。随之而来的是海量的信息涌入,品牌需要及时了解并应对海外社交媒体上的舆情变化。本文将介绍如何通过云手机进行境外舆情监控,更好地帮助企业公关及时作出决策。 1. 境外舆情监控与…

【linux】linux系统调用及文件IO操作

一、系统调用 1、概述 系统调用: 就是操作系统内核 提供给用户可以操作内核 一组函数接口。用户 借助 系统调用 操作内核。比如用户可以通过文件系统相关的调用请求系统打开文件、关闭文件或读写文件,可以通过时钟相关的系统调用获得系统时间或设置定时…

如何创建测试计划?这些要考虑到

以下为作者观点: 创建一个彻底和有效的测试计划对软件测试的成功至关重要。它可以帮助识别过程中可能出现的潜在问题或问题。 什么是测试计划? 测试计划是一份文件,概述了软件测试过程的策略、目标、资源和时间表。测试计划通常包括一些细…

uniapp 项目 浏览器chrome使用vue devtool 识别不了 in not detect

问题 uniapp的项目,vue2, chrome 分析 添加了运行时,指定模板h5.html 指定的h5.html重置了运行根目录,导致了vue dev tool在运行时,chrome上识别不了。 解决: 方法1: 只能调试的时候,不加sati…

java常用应用程序编程接口(API)——Arrays概述

前言: 学到Arrays了,整理下心得。打好基础,daydayup! Arrays 用来操作数组的一个工具类 Arrays的常见方法 方法名说明public static String toString(类型[] arr)返回数组的内容public static int[ ] copyOfRange(类型[ ] arr,启示索引&…

Linux - 安装 maven(详细教程)

目录 一、下载二、安装三、配置环境变量四、镜像资源配置 一、下载 官网:https://maven.apache.org/download.cgi 打开 maven 的官网下载页面,点击 bin.tar.gz 文件链接 即可下载最新版本的 maven 如果想要下载旧版本的 meven,则点击 Maven…

图形系统开发实战课程:进阶篇(上)——9.空间算法(一)

图形开发学院|GraphAnyWhere 课程名称:图形系统开发实战课程:进阶篇(上)课程章节:“图形样式”原文地址:https://www.graphanywhere.com/graph/advanced/2-9.html 第九章 空间算法(一) \quad 在…

SpringBoot 自定义映射规则resultMap collection一对多

介绍 collection是封装一对多关系的,通常情况下是一个列表,association是一对一,通常情况是一个对象。例如:查询班级下所有的学生,一个班级可以有多个学生,这就是一对多。 案例 有一个学生表&#xff0c…

Go语言中的时间控制:定时器技术详细指南

Go语言中的时间控制:定时器技术详细指南 引言定时器基础创建和使用time.Timer使用time.Ticker实现周期性任务定时器的内部机制小结 使用time.Timer实现简单的定时任务创建和启动定时器停止和重置定时器定时器的实际应用小结 利用time.Ticker处理重复的定时任务创建和…

这里推荐一款unity3d人物动物控制器详细的等学会再写文章

unity3d Animal Controller 1.4.0a 动物NPC行为控制器 动物控制器(AC)是一个基于脚本架构的动画框架控制器。它适用于任何动物或人形角色的根运动或原地动画。 人和动物的各种动作都有; 小白必选、 我只是运行乐demo就感觉牛 demo路径:Asset…

Python不换行print在终端中不显示

问题描述 当使用不换行 print 即 print(‘test, end) 后立即关闭标准输出 sys.stdout open(os.devnull, w)则 print 的内容不会显示在正常的终端上(例外是 PyCharm 中的终端能够正常显示)。 复现问题 复现该问题的简易代码: import sys,…

基于pytorch的手写体识别

一、环境搭建 链接: python与深度学习——基础环境搭建 二、数据集准备 本次实验用的是MINIST数据集,利用MINIST数据集进行卷积神经网络的学习,就类似于学习单片机的点灯实验,学习一门机器语言输出hello world。MINIST数据集,可以…

【go从入门到精通】go环境安装和第一个经典程序

go下载和环境变量配置 下载地址 Go官网下载地址:https://golang.org/dl/All releases - The Go Programming Languagehttps://golang.org/dl/ 然后根据自己的系统环境来选择不同的安装包下载,下面我分别针对不同环境进行说明(大家可以根据自…

Platformview在iOS与Android上的实现方式对比

Android中早期版本Platformview的实现基于Virtual Display。VirtualDisplay方案的原理是,先将Native View绘制到虚显,然后Flutter通过从虚显输出中获取纹理并将其与自己内部的widget树进行合成,最后作为Flutter在 Android 上更大的纹理输出的…