Android 基础技术——Handler

news2024/11/18 0:29:36
笔者希望做一个系列,整理 Android 基础技术,本章是关于 Handler
为什么一个线程对应一个Looper?

核心:通过ThreadLocal保证

Looper.prepare的时候,ThreadLocal.get如果不空报异常;否则调用ThreadLocal.set, ThreadLocal.set 会调用当前线程Thread里的ThreadLocalmap  put 键值对,put 的键值对就是 Key = ThreadLocal, Value = Looper

线程里有TreadLocalMap的成员变量  Key = ThreadLocal,  Value = Looper   

Looper 中有一个 static final 的成员变量就是 ThreadLocal,意味着唯一性

 Looper有final的成员MessageQueue

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

可以有多个

Handler内存泄漏的原因

匿名内部类handler 默认持有外部类的activity的引用。

并且Handler.enqueMessage的时候, msg.target = handler, message持有了handler,

引用链:msg->handler->activity或者fragment

为什么主线程可以New handler; 子线程new handler需要做什么

子线程 必须 Looper.prepare + Looper.loop

主线程   在ActivityThread.main方法里  帮你Looper.prepareMainLoop和Looper.loop

子线程中维护的looper,消息队列无消息的时候处理方案是什么?有什么作用?

主线程会阻塞,主线程不能调用quit

子线程没有消息的时候,需要调用quit 

这个quit作用:唤醒线程;

调用 quit 后,messagequeue返回null 退出loop

消息的睡眠的唤醒机制是怎样的?

生产者消费者模式

入队满的时候  阻塞    这个handler没有限制满的情况

出队空的时候 阻塞

java的多线程里有阻塞队列,但是handler不是这样,没有限制消息个数

nativePollOnce 到了C++层 会调用epoll_wait等待, 阻塞整个线程, CPU释放

nativeWake 到了C++层调用 epoll 的wake

多个handler往messagequeue发送消息 如何保证线程安全

通过两点来保证线程安全:

一个线程只有一个messageQueue

使用synchronized, 内置锁,加锁和释放是JVM帮我们完成的,锁的是MessageQueue 对象里面的所有函数/代码块都受限

子线程发送消息,为什么能在主线程接收,也就是线程是如何切换的

子线程thread: handler.sendMessage->MessageQueue.enqueMessage.

MessageQueue是没有线程之说。他是一个数据结构,内存共享

主线程loop   轮询MessageQueue。这个时候MessageQueue.next在主线程执行。

 ThreadLocal整个系统只有一个吗? 会不会有矛盾

线程1-ThreadLocalMap1  唯一的ThreadLocal-looper1

线程2-ThreadLocalMap2  唯一的ThreadLocal-looper2

一个线程对应一个Looper,一个Looper 对应一个 ThreadLocal

调整系统时间对延时消息有没影响

Handler的延迟消息计算是通过SystemClock类来计算,跟系统时间没有任何关系,这是根据Handler自启动以来非睡眠正常运行时间的毫秒数和代码指定的postDelayed的时间来计算的。

我们使用Message如何创建?

通过obtainMessage

享元设计模式: 内存复用,android中使用非常广泛  如recyclerView

维持一个消息池,防止内存碎片->内存抖动->OOM

消息释放后,插入到队列头部,重置队头为这个消息节点

Looper死循环为什么不会导致卡死

和anr无关。

为什么msg 阻塞不会导致anr?  

这个阻塞是指线程没有事情做了,释放cpu,休眠

什么是同步屏障?

msg.target=null 的消息就是同步屏障

同步屏障的场景:刷新UI    ViewRootImpl   scheduleTraversals---> postSyncBarrier 在对头插入节点

同步屏障的删除:ViewRootImpl   unScheduleTraversals---->removeSyncBarrier  删除屏障的节点

同步屏障:就是把同步消息给屏障掉了!! 然后优先执行异步消息(setAsynchrious标志)

messageQueue.next的时候  

先判断 如果msg.target==null  轮询消息队列,直到找到一个异步消息为止,执行这个异步消息。

setAsynchrious(true)这个标志。

刷新UI 使用了同步屏障就是为了保证及时执行消息,如果保证不了16ms 刷新一次, 会导致掉帧。

我们平时发送到消息是同步消息

同步屏障的作用是什么??

我们向主线程发送了一个UI绘制操作Message,而此时消息队列中的消息非常多,那么这个Message的处理可能会得到延迟,绘制不及时造成界面卡顿。同步屏障机制的作用,是让这个绘制消息得以越过其他的消息,优先被执行。

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

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

相关文章

376. 摆动序列 - 力扣(LeetCode)

题目描述 如果连续数字之间的差严格地在正数和负数之间交替,则数字序列称为摆动序列。第一个差(如果存在的话)可能是正数或负数。少于两个元素的序列也是摆动序列。 例如, [1,7,4,9,2,5] 是一个摆动序列,因为差值 (6,…

项目中从需求分析到研发上线

一、背景 应用系统从设想到需求到研发到上线会经历一些列工程化过程。比如经典的瀑布模型工作流,其实就是一个经过很多经验总结下来的工程方法。本节阐述项目中从需求到研发上线的过程。但是也有些根据不同的行业,不同的公司,不同管理者的风…

Cesium加载地图-高德影像

废话不多说&#xff0c;直接上代码 整体代码 <template><div id"cesiumContainer" style"height: 100vh;"></div><div id"toolbar" style"position: fixed;top:20px;left:220px;"><el-breadcrumb><…

【数据结构与算法】5.详解双向链表的基本操作(Java语言实现)

&#x1f4da;博客主页&#xff1a;爱敲代码的小杨. ✨专栏&#xff1a;《Java SE语法》 ❤️感谢大家点赞&#x1f44d;&#x1f3fb;收藏⭐评论✍&#x1f3fb;&#xff0c;您的三连就是我持续更新的动力❤️ &#x1f64f;小杨水平有限&#xff0c;欢迎各位大佬指点&…

Oracle扩展ASM存储

物理增加1T存储到服务器。 , 绑定裸设备 vi /etc/udev/rules.d/99-asmdevice.rules KERNEL"dm-*",ENV{DM_UUID}"mpath-360002ac000000000000001a700006bc6",NAME"asm_arch",OWNER"grid",GROUP"asmadmin",MODE"0660&q…

第二百八十八回

文章目录 1. 概念介绍2. 使用方法2.1 实现步骤2.2 具体细节 3. 示例代码4. 内容总结 我们在上一章回中介绍了"如何获取文件类型"相关的内容&#xff0c;本章回中将介绍如何播放视频.闲话休提&#xff0c;让我们一起Talk Flutter吧。 1. 概念介绍 播放视频是我们常用…

区块空间----流动性铭文

铭文正在改变加密世界&#xff0c;越来越多的人开始关注铭文&#xff0c;并参与进来&#xff01;铭文赛道的未来是非常具有潜力和想象力的&#xff0c;甚至能够达到加密货币的普及水平。当然&#xff0c;这需要更多的基础设施更多的用例支持&#xff0c;但是一切都才刚刚开始。…

Go语言grpc服务开发——Protocol Buffer

文章目录 一、Protocol Buffer简介二、Protocol Buffer编译器安装三、proto3语言指南四、序列化与反序列化五、引入grpc-gateway1、插件安装2、定义proto文件3、生成go文件4、实现Service服务5、gRPC服务启动方法6、gateway服务启动方法7、main函数启动8、验证 相关参考链接&am…

Mysql-日志介绍 日志配置

环境部署 docker run -d -p 3306:3306 --privilegedtrue -v $(pwd)/logs:/var/lib/logs -v $(pwd)/conf:/etc/mysql/conf.d -v $(pwd)/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD654321 --name mysql mysql:5.7运行指令的目录下新建好这些文件&#xff1a; 日志类型 日…

dhcp服务器的ip池的待分配ip地址是否冲突的检测机制

看到有的资料说&#xff0c;dhcp服务器在分配ip地址时&#xff0c;要检测是否待分配的ip地址是否存在冲突&#xff0c;会向广播域发出&#xff0c;对应ip发出icmp的ping消息来验证是否冲突。特地用自己的公司的交换机验证一下&#xff0c;在交换机上镜像抓包观察一下。 wiresha…

社交媒体与新闻:Facebook在信息传播中的角色

社交媒体的崛起不仅改变了人们的日常交流方式&#xff0c;也对新闻传播产生了深远的影响。在众多社交媒体平台中&#xff0c;Facebook以其庞大的用户基础和强大的社交网络机制&#xff0c;成为信息传播的中流砥柱。本文将深入探讨Facebook在社交媒体与新闻传播的交汇点上扮演的…

Qt应用开发(安卓篇)——调用java代码,使用安卓api

一、前言 在Qt on Android开发的时候&#xff0c;它不像在嵌入式linux&#xff0c;几乎全部的操作都是可以通过文件来完成。很多场景下的功能都需要使用安卓的API去实现&#xff0c;开发人员需要通过这些API进行编程&#xff0c;无需访问源码&#xff0c;或者理解内部的机制。比…

IP报文格式

IP报文格式 报文格式 图1 IP头格式 表1 IP头字段解释 字段长度含义Version4比特 4&#xff1a;表示为IPV4&#xff1b;6&#xff1a;表示为IPV6。IHL4比特首部长度&#xff0c;如果不带Option字段&#xff0c;则为20&#xff0c;最长为60&#xff0c;该值限制了记录路由选项。…

阅读go语言工具源码系列之gopacket(谷歌出品)----第二集 layers-巧妙的抽象与无聊的协议包

上一集中我们讲到了wpcap.dll的go封装方法&#xff0c;对于linux系统下libpcap的go封装采用的是常用的cgo方式&#xff0c;想了解的可以看看pcap文件夹中的pcap_unix.go。 我们得到了wpcap.dll的go调用&#xff0c;就可以利用它来进行列举所有网络设备&#xff0c;例如以下代码…

docker容器生命周期管理命令

文章目录 前言1、docker create2、docker run2.1、常用选项2.2、系统2.3、网络2.4、健康检查 3、docker start/stop/restart4、docker kill5、docker rm6、docker pause/unpause总结 前言 在云原生时代&#xff0c;Docker已成为必不可少的容器管理工具。通过掌握Docker常用的容…

派网AX50C做多宽带路由和核心交换机配置实战教程

接近300办公人员的工厂需要网络升级&#xff0c;我规划设计和部署实施了以下方案&#xff0c;同样是简约不简单&#xff0c;在满足性能需求稳定性的前提下&#xff0c;既有经济性&#xff0c;又有安全性。 派网做路由器&#xff0c;刚好开启默认防病毒策略&#xff0c;省下来一…

【QT+QGIS跨平台编译】之十一:【libzip+Qt跨平台编译】(一套代码、一套框架,跨平台编译)

文章目录 一、libzip介绍二、文件下载三、文件分析四、pro文件五、编译实践一、libzip介绍 libzip是一个开源C库,用于读取,创建和修改zip文件。 libzip可以从数据缓冲区,文件或直接从其他zip归档文件直接复制的压缩数据中添加文件。在不关闭存档的情况下所做的更改可以还原…

TCP 状态转换以及半关闭

TCP 状态转换&#xff1a; 上图中还没有进行握手的时候状态是关闭的。 三次握手状态的改变&#xff1a; 客户端发起握手。 调用 connect() 函数时状态转化为&#xff1a;SYN_SENT。调用 listen() 函数时状态转换为&#xff1a;LISTEN。ESTABLISHED是被连接的状态。 四次挥手…

林浩然的哲学奇遇记:与罗素一起穿越西方哲学史

林浩然的哲学奇遇记&#xff1a;与罗素一起穿越西方哲学史 The Philosophical Adventures of Lin Haoran: Journeying Through Western Philosophy with Russell 在一个阳光灿烂的早晨&#xff0c;林浩然同学迎着微风&#xff0c;拿着一本厚重的罗素名著《西方哲学史》&#xf…

了解维特比算法:通信系统和自然语言处理中解码的基石

一、介绍 在数字通信和信号处理领域&#xff0c;维特比算法是一种革命性的纠错和解码方法。该算法以 1967 年推出的 Andrew Viterbi 的名字命名&#xff0c;已成为数字通信和自然语言处理领域的基础。本文旨在深入研究维特比算法的复杂性&#xff0c;探讨其理论基础、实际应用以…