Handler的消息机制与消息延迟代码实现

news2024/12/23 22:19:21

Handler的作用

Handler消息机制在Android中的应用非常广泛,很多组件的底层实现都是靠Handler来完成的,所以掌握Handler消息机制的原理还是非常重要的。Handler的主要功能有两点:

1.它可以在不同的线程之间传递消息

我们都知道Andorid中规定只有主线程里可以进行UI操作,在其他线程中绝不可以进行与UI相关的操作,否则会报错。还有就是在主线程中也不可以进行耗时操作,否则会阻塞主线程,报ANR。基于以上这两点,我们就可以使用Handler在子线程中处理耗时操作,然后把返回的结果传给主线程,再进行UI方面的更新处理等。

2.它可以延时传递消息。

如果我们想要处理一个延时操作,一般可以通过Thread.sleep(times)使线程休眠几秒,然后再处理数据。但是再Android中是绝不能允许在主线程红进行休眠操作阻塞线程的,所以我们可以通过Handler来发送延迟消息的方式实现延时操作。

消息处理机制

Android的消息处理机制表面上只是使用了Handler,但其实还用到了其他的东西,比如说ThreadLocal,Looper,MessageQuery等,这些组合在一起使用,才构成了整个Android消息机制。

我们先回顾一下Handler的使用:我们以 “在子线程处理完耗时操作,然后通过Handler发送消息到主线程更新UI”为例。首先要先在主线程创建一个Handler对象,重写它的handlerMessage()方法,处理更新UI的操作。然后我们在子线程进行处理耗时操作,当执行完成后,我们创建一个Message对象,将需要传递的数据存入Message对象中,再调用Handler对象的sendMessage()方法将该Message对象发送出去。之后我们就能在Handler的handlerMessage()方法中接收到该Message对象了,然后取出其中的数据,进行更新UI的操作即可,这样整个过程就算完成了。

上面说的例子是从子线程发送消息回主线程,然后再主线程中处理消息。如果是通过主线程发送消息到子线程,然后在子线程处理消息,那又应该如何做呢?我们尝试直接在子线程中创建Handler对象,重写handlerMessage()方法,然后在主线程中发送消息,但程序运行后会报如下错误:

java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()

意思是“不能够在一个没有执行过Looper.prepare()方法的线程中去创建Handler对象”,到这里我们终于能够看到Looper的影子了。那么这里就有一个问题,为什么在主线程中没有要求我们先调用Looper.prepare()方法呢,或者说与普通线程相比,主线程有什么特别的吗?

其实这是因为在主线程中,系统已经调用过该方法了,所以不需要我们再去手动调用。代码如下,主线程在刚开始创建的时候它的Looper就已经调用了prepareMianLooper()方法,所以我们能直接创建Handler。

public final class ActivityThread { 
   public static void main(String[] args) {
​
        ...
​
        Looper.prepareMainLooper();
​
        ActivityThread thread = new ActivityThread();
        thread.attach(false);
​
        if (sMainThreadHandler == null) {
            sMainThreadHandler = thread.getHandler();
        }
​
        if (false) {
            Looper.myLooper().setMessageLogging(new
                    LogPrinter(Log.DEBUG, "ActivityThread"));
        }
​
        // End of event ActivityThreadMain.
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        Looper.loop();
​
        throw new RuntimeException("Main thread loop unexpectedly exited");
    }
}

Handler消息延迟

Handler 的延迟发送是依靠

nativePollOnce(ptr, nextPollTimeoutMillis);

这个方法中的nextPollTimeoutMills 表明了阻塞等待时间。

nextPollTimeoutMillis = (int)Math.min(msg.when - now, Interge.MAX_VALUE);

原理:

当sendMessage 时,enququeMessage()@MessageQueue 会将消息按照按照实际执行时间顺序(即msg.when)插入到队列,然后执行nativeWake()唤醒,随后执行到next()@MessageQueue 中的nativePollOnce()处,这里是一个 for 死循环,唤醒后计算出根据now 和msg.when,如果now < msg.when 则计算出nextPollTimeoutMillis,下一个循环赋值给nativePollOnce(ptr,nextPollTimeoutMillis),告诉阻塞时间。

其实 Java 层的 Handler 只是利用到了 native 层的 NativeMessageQueue和 native 层的 Looper 来完成阻塞和唤醒工作。消息队列的插入和消息的读取都是在 Java 层完成的 。当MessageQueue 在nativePollOnce()被nextPollTimeoutMillis 阻塞时,当有另外一个消息入队进行唤醒时,nativePollOnce()的阻塞状态立即被唤醒,然后进行处理消息,当发现now < msg.when 时,根据新的阻塞时间进行等待。因为消息在入队时根据msg.when 进行排列了。

代码实现

Handler mHandler;
​
mHandler=new Handler(){
public void dispatchMessage(android.os.Message msg) {
switch (msg.what) {
case 1:
Intent mIntent=new Intent();
mIntent.setClass(SetPassActivity.this, MainActivity.class);
startActivity(mIntent);
break;
​
default:
break;
}
};
};
mHandler.sendEmptyMessageDelayed(1, 2000);

以上就是Handler的消息机制介绍以及他的消息延迟操作代码实现;想要深入了解Handler的知识点,或者更多Android技术可以参考文献《Android核心技术手册》点击前往查看。里面技术板块30多个技术点上千个。

文末

Handler 机制源码图解

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

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

相关文章

menuconfig与Kconfig入门学习

概述 menuconfig是Linux平台用于管理代码工程、模块及功能的实用工具。 menuconfig的使用方式通常是在编译系统之前在系统源代码根目录下执行make menuconfig命令从而打开一个图形化配置界面&#xff0c;再通过对各项的值按需配置从而达到影响系统编译结果的目的。 Nuttx的m…

新建一个SpringMVC项目

步骤1:创建Maven项目 打开IDEA,创建一个新的web项目 步骤2:补全目录结构 因为使用骨架创建的项目结构不完整&#xff0c;需要手动补全 步骤3:导入jar包 将pom.xml中多余的内容删除掉&#xff0c;再添加SpringMVC需要的依赖 <?xml version"1.0" encoding"UT…

一文读懂远程线程注入

在红队行动中&#xff0c;红队的目的都是要在不暴露自身行动的前提下&#xff0c;向蓝队发动攻击。他们使用各种技术和程序来隐藏C2连接和数据流。攻击活动的第一步是获得初始访问权。他们会使用定制的恶意软件和有效载荷来躲避防杀软和EDR等防御工具。 在这些典型的攻击活动中…

代码中大量爆红,IDE设置jdk版本,及设置后无效的解决

代码大量爆红&#xff0c;检查ide设置的jdk版本是否与项目的java版本一致&#xff0c;做以下配置 1.project structrue 2.maven 3.如果以上设置以后没有效果&#xff0c;就把项目中的.ide文件删除&#xff0c;并且pom里面加上下面的代码&#xff0c;重启IDE。 <build&g…

植物大战僵尸:植物栏无冷却的找法

通过使用CE遍历内存&#xff0c;定位到植物无冷却的核心代码处&#xff0c;并通过修改关键的跳转来实现所有植物的无冷却。 第一种遍历修改方式 无冷却的遍历技巧1&#xff1a; 打开CE->回到游戏种植一颗向日葵 -> 扫描未知初始数值然后切回游戏 ->马上切回CE ->…

< JavaScript技术分享: 大文件切片上传 及 断点续传思路 >

文章目录&#x1f449; 前言及含义切片上传断点续传&#x1f449; 一、实现思路&#x1f449; 二、使用场景&#x1f449; 参考文献&#x1f449; 伸手党福利&#xff1a; 即拿即用&#xff08;前/后端思路均有&#xff09;往期内容 &#x1f4a8;&#x1f449; 前言及含义 在…

MVVM学习

mvvm基础知识Model&#xff1a;repository Entity 数据库 网络访问等对数据进行直接操作的代码View:视图代码 xml activity fragment adapter 等ui层的一些代码ViewModel:视图模型 用来和View ,Model层交互&#xff0c;将Model层的数据显示到View上&#xff0c;并处理View层的事…

Android Softap Mac地址随机化

目录 Android Q以后 Android Q 获取方式 Android Q以后 在SoftapManager创建的时候,可以跟下 Android Q Q:WifiManager#getWifiApConfiguration()只能获取到SSID和pwd等,无法获取到对应的BSSID。 原因分析:Android Q Softap的MAC地址设置是在HAL层,并没有给Framework赋…

result.isAck()报错

IDEA 的 bug&#xff0c;两张图解释

图像平滑处理

平滑处理是指在某些数学和统计分析中&#xff0c;对于原始数据做出拟合&#xff0c;并生成更平滑的数据。这通常是为了抑制原始数据中的离群点或噪声&#xff0c;使得数据更具可读性和可解释性。 在图像处理中常用于模糊处理和降低噪声。平滑滤波器使用给定邻域内的像素平均灰度…

Word处理控件Aspose.Words功能演示:在 C# .NET 中将 Word 转换为 PDF - 完整指南

Aspose.Words 是一种高级Word文档处理API&#xff0c;用于执行各种文档管理和操作任务。API支持生成&#xff0c;修改&#xff0c;转换&#xff0c;呈现和打印文档&#xff0c;而无需在跨平台应用程序中直接使用Microsoft Word。此外&#xff0c; Aspose API支持流行文件格式处…

JS面试题--JavaScript基础

1. new操作符的实现原理 创建一个对象将构造函数的作用域赋给新对象&#xff08;也就是将对象的__proto__属性指向构造函数的prototype属性&#xff09;指向构造函数中的代码&#xff0c;构造函数中的this指向该对象&#xff08;也就是为这个对象添加属性和方法&#xff09;返…

Arthas tt -t , tt -i 以及 watch相关使用理解 解析入参和结果等

Arthas tt 系列作用 方法执行数据的时空隧道&#xff0c;记录下指定方法每次调用的入参和返回信息&#xff0c;并能对这些不同的时间下调用进行观测 一、 tt -t 作用和一般用法 tt -t 一般用于监控某一个方法的调用记录&#xff0c;如果调用多此会出现多条记录&#xff0c;一…

怎么申请icp备案?怎么查询icp备案是否申请成功

什么是icp备案号&#xff1f; 简单来说&#xff0c;icp备案号&#xff0c;就是你网站的备案号码。icp备案号就是当你的网站提交备案资料&#xff0c;经工业信息化产业部&#xff08;及各地通信管理局&#xff09;审核通过后&#xff0c;会通过电子邮箱发送一个备案号码给你…

JVM内存结构及内存溢出OOM

JVM内存结构JVM的内存结构大致分为五个部分&#xff0c;分别是程序计数器、虚拟机栈、本地方法栈、堆和方法区。除此之外&#xff0c;还有由堆中引用的JVM外的直接内存。下面将展开讲解这五个部分。程序计数器程序计数器(Program Counter Register)&#xff0c;用于记录下一条J…

券商接口关闭的情况下怎么做到实时量化买入?通达信破解接口可以吗?

现在券商接口关闭的情况下怎么做到实时量化买入&#xff1f;量化买入有一些第三方软件是可以破解券商接口的。像通达信破解接口它有一个什么机构版还是什么&#xff0c;他可以同时几个券商一起买入&#xff0c;当然这个你需要用手工输入。像其他的像一些A计划&#xff0c;它就是…

【 java 集合】List接口常用实现类对比以及ArrayList和LinkedList源码分析

&#x1f4cb; 个人简介 &#x1f496; 作者简介&#xff1a;大家好&#xff0c;我是阿牛&#xff0c;全栈领域优质创作者。&#x1f61c;&#x1f4dd; 个人主页&#xff1a;馆主阿牛&#x1f525;&#x1f389; 支持我&#xff1a;点赞&#x1f44d;收藏⭐️留言&#x1f4d…

绿控传动冲刺科创板上市:连年亏损,现金流紧张,计划募资11亿元

近日&#xff0c;苏州绿控传动科技股份有限公司&#xff08;下称“绿控传动”&#xff09;在上海证券交易所递交招股书&#xff0c;准备在科创板上市。 本次冲刺上市&#xff0c;绿控传动计划募资10.72亿元&#xff0c;其中7.16亿元用于年产新能源商用车电驱动系统10万套项目&a…

泛微特色政务应用:对内协同办公、对外高效服务,推动政务数字化

近年来&#xff0c;国家不断深入建设“数字化政府”&#xff0c;政务服务“网上办”、“掌上办”、“一网通办”已经成为政务服务新方向。 泛微数字化运营平台为各级政府机关、行政事业单位&#xff0c;打造覆盖各级市、区、县、乡镇街道、村及各级社区部门的网上协同办公平台…

Qt编译CTK

文章目录一、CTK简介二、CTK下载三、CTK编译一、CTK简介 CTK是什么 CTK 为支持生物医学图像计算的公共开发包&#xff0c;其全称为 Common Toolkit CTK 提供了什么 当前&#xff0c;CTK 工作的主要范围包括&#xff1a; DICOM&#xff1a;提供了从 PACS 和本地数据库中查询和…