避免误差!Android 中正确计算时间差的方式
在 Android 开发中,计时和计算时间差异是非常常见的需求,比如记录事件发生的间隔、统计应用启动时间、测量网络请求的响应时间等。在实现这些功能时,我们通常需要一个可靠的时间源来确保计时的准确性。那么为什么 Android 推荐使用 SystemClock.elapsedRealtime() 来计算时间差异,而不建议使用 System.currentTimeMillis() 呢?本文将详细探讨这个问题。
System.currentTimeMillis() 和 SystemClock.elapsedRealtime() 的区别
在 Android 中,System.currentTimeMillis() 和 SystemClock.elapsedRealtime() 都能获取时间,但两者之间存在明显差异:
-
System.currentTimeMillis() :返回的是当前的“系统时间”,从 1970 年 1 月 1 日 UTC 以来的毫秒数。这个时间可以通过网络同步、用户手动更改等方式调整,时间的准确性和连续性不一定可靠。 -
SystemClock.elapsedRealtime() :返回的是设备自上次启动以来的毫秒数。该计时器是 单调递增的,也就是说,即使系统时间被调整,或者设备进入了待机模式,这个计时器也会保持更新,始终提供可靠的时间差。
为什么选择 SystemClock.elapsedRealtime() 计算时间差异?
在 Android 中,更推荐使用 SystemClock.elapsedRealtime() 来计算时间差异,主要基于以下几点原因:
1. 时间连续性和稳定性
System.currentTimeMillis() 可能会因为系统时间的调整而出现时间跳变或倒退,比如用户手动更改时间、网络时间同步等。这会导致时间间隔的计算结果不准确。
相反,SystemClock.elapsedRealtime() 是设备启动后的时间流逝计时,不会受到系统时间调整的影响。这就保证了在任何情况下,使用 SystemClock.elapsedRealtime() 来计算的时间差值都是稳定和连续的。因此,如果你希望获得可靠的时间差,那么 elapsedRealtime() 是更好的选择。
2. 适合计算相对时间差
在 Android 开发中,SystemClock.elapsedRealtime() 更适合用于计算两个时间点之间的相对时间差。因为它仅仅表示系统启动后的流逝时间,不关心系统当前的时间和日期,也不会受到系统时间变化的影响。这种设计非常适合用于统计两个事件的时间差。
例如,你可以用 SystemClock.elapsedRealtime() 来测量应用启动时间、功能执行耗时,或统计用户打开某个页面的时间差。只要记录开始和结束时间的 elapsedRealtime() 值,差值即为准确的流逝时间。
3. 设备休眠不影响计时
SystemClock.elapsedRealtime() 会考虑设备的休眠状态,即使设备进入待机状态,elapsedRealtime() 计时器也会继续更新。这意味着即便设备休眠,计时结果也不会中断或失效。这对许多需要跨越设备待机的计时操作来说非常重要,比如统计用户停留在某个页面的总时间。
相较之下,System.currentTimeMillis() 无法保证这一点,因为系统时间的变化会干扰计时效果。对于需要高精度的计时需求,elapsedRealtime() 显然更加适用。
使用场景对比
下面列举一些常见的场景,分别说明适合 SystemClock.elapsedRealtime() 和 System.currentTimeMillis() 的情况:
| 使用场景 | 推荐方法 | 原因 |
|---|---|---|
| 计算两个事件的时间间隔 | SystemClock.elapsedRealtime() | 保证计时的准确性和连续性,不受系统时间调整影响 |
| 记录日志时间戳 | System.currentTimeMillis() | 需要绝对的时间信息来标记事件的发生时间 |
| 网络请求的响应时间 | SystemClock.elapsedRealtime() | 计时不受系统时间调整影响,确保响应时间的准确性 |
| 应用启动时间或活动的运行时长 | SystemClock.elapsedRealtime() | 提供稳定的相对时间,适合统计启动或运行耗时 |
| 获取当前日期和时间 | System.currentTimeMillis() | 返回系统时间,以获取绝对的日期时间(如显示给用户或存储) |
示例代码:如何用 SystemClock.elapsedRealtime() 计算时间差
假设我们要测量某个操作的执行耗时,以下是使用 SystemClock.elapsedRealtime() 的实现方式:
// 记录操作开始的时间戳long startTime = SystemClock.elapsedRealtime();// 执行操作performOperation();// 记录操作结束的时间戳long endTime = SystemClock.elapsedRealtime();// 计算操作耗时long duration = endTime - startTime;Log.d("Timing", "操作耗时:" + duration + " 毫秒");
在这个例子中,startTime 和 endTime 都是使用 SystemClock.elapsedRealtime() 获取的,即便系统时间发生调整,duration 也会是准确的操作耗时。
SystemClock 中的其他计时方法
SystemClock 类中还提供了其他几种有用的计时方法:
-
SystemClock.uptimeMillis() :返回设备自启动以来的时间,但不包括设备休眠的时间。适合用于计时操作,不受系统时间调整影响,但会忽略休眠状态。 -
SystemClock.currentThreadTimeMillis() :返回当前线程的 CPU 时间,不包括其他线程的耗时。这在分析特定线程的执行时间时非常有用。
总结
在 Android 开发中,SystemClock.elapsedRealtime() 是计算时间差异的最佳选择,尤其是当计时过程可能跨越系统待机或涉及高精度的时间间隔计算时。它的单调递增特性和独立于系统时间调整的特点,确保了计时的连续性和稳定性。而 System.currentTimeMillis() 更适合用来获取绝对的系统时间,例如记录日志时间、事件的发生时间等。
选择合适的计时方法,不仅可以避免时间误差带来的影响,还能提升应用性能,确保计时功能的可靠性。希望本文能帮助你在实际开发中理解和应用这些计时方法,写出更高效、准确的 Android 应用!
相关文章:
避免误差!Android 中正确计算时间差的方式
在 Android 开发中,计时和计算时间差异是非常常见的需求,比如记录事件发生的间隔、统计应用启动时间、测量网络请求的响应时间等。在实现这些功能时,我们通常需要一个可靠的时间源来确保计时的准确性。那么为什么 Android 推荐使用 SystemClo…...
unity3d————Resources异步加载
知识点一:Resources异步加载是什么? 在Unity中,资源加载可以分为同步加载和异步加载两种方式。同步加载会在主线程中直接进行,如果加载的资源过大,可能会导致程序卡顿,因为从硬盘读取数据到内存并进行处理…...
YOLOv11改进,YOLOv11添加GnConv递归门控卷积,二次创新C3k2结构
摘要 视觉 Transformer 在多种任务中取得了显著的成功,这得益于基于点积自注意力的新空间建模机制。视觉 Transformer 中的关键因素——即输入自适应、长距离和高阶空间交互——也可以通过卷积框架高效实现。作者提出了递归门控卷积(Recursive Gated Convolution,简称 gnCo…...
如何选择国产化CMS来建设政务网站?
在介绍CMS之前,我们先了解国家为什么要网站为什么要完成国产化改造? 1、信创国产化网站建站响应了国家的信息安全战略,支持自主可控的信息技术产业的发展,减少对进口软硬件的依赖,保障国家信息安全。 2、国产替代&…...
C/C++语言基础--initializer_list表达式、tuple元组、pair对组简介
本专栏目的 更新C/C的基础语法,包括C的一些新特性 前言 initializer_list表达式、tuple元组、pair对组再C日常还是比较常用的,尤其是对组在刷算法还是挺好用的,这里做一个简介;这三个语法结合C17的结构化绑定会更好用ÿ…...
paddle表格识别数据制作
数据格式 其中主要数据有两个一个表格结构的检测框,一个是tokens,注意的地方是 1、只能使用双引号,单引号不行 2、使用带引号的地方是tokens里面 "<tr>", "<td", " colspan2", ">",&quo…...
python selenium库的使用:通过兴趣点获取坐标
通过兴趣点获取坐标 from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.common.keys import Keys from selenium.common.exceptions import TimeoutException# 保存Cookies到文件(可选) import pi…...
如何优化Kafka消费者的性能
要优化 Kafka 消费者性能,你可以考虑以下策略: 并行消费:通过增加消费者组中的消费者数量来并行处理更多的消息,从而提升消费速度。 批量消费:配置 fetch.min.bytes 和 fetch.max.wait.ms 参数来控制批量消费的大小和…...
机器学习 决策树
决策树-分类 1 概念 1、决策节点通过条件判断而进行分支选择的节点。如:将某个样本中的属性值(特征值)与决策节点上的值进行比较,从而判断它的流向。 2、叶子节点没有子节点的节点,表示最终的决策结果。 3、决策树的深度所有节点的最大层…...
效益登记册效益管理计划
效益登记册 benefit Register效益管理计划效益登记册汇集并列出项目集计划的效益,用于在项目集的整个持续时间内测量和沟通效益的交付。在效益识别阶段,效益登记册根据项目集商业论证、组织战略计划和其他相关项目集自标而编制。随后,登记册由…...
Go语言的零值可用性:优势与限制
Go语言以其简洁和高效的设计理念而著称,其中之一便是“零值可用”的特性。这一特性使得许多类型在未显式初始化时即可直接安全地使用,大大简化了代码的初始化过程。然而,并非所有类型都支持零值可用,且在使用时也存在一定的限制。…...
【自用】0-1背包问题与完全背包问题的Java实现
引言 背包问题是计算机科学领域的一个经典优化问题,分为多种类型,其中最常见的是0-1背包问题和完全背包问题。这两种问题的核心在于如何在有限的空间内最大化收益,但它们之间存在一些关键的区别:0-1背包问题允许每个物品只能选择…...
HTML5实现俄罗斯方块小游戏
文章目录 1.设计来源1.1 主界面1.2 皮肤风格1.2 游戏中界面1.3 游戏结束界面 2.效果和源码2.1 动态效果2.2 源代码 源码下载 作者:xcLeigh 文章地址:https://blog.csdn.net/weixin_43151418/article/details/143788449 HTML5实现俄罗斯方块小游戏&#x…...
Mybatis官方生成器使用示例
在这篇文章中,我们将通过实际代码示例来说明如何使用 MyBatis Generator (MBG) 来自动化生成 MyBatis 项目所需的实体类、Mapper 接口和 Mapper XML 文件。我们将使用一个 Maven 插件来执行代码生成,并提供详细的配置和解释。 1. MyBatis Generator 简介…...
演员王子辰—专注革命题材 《前行者》后再出发
2021年10月22日在北京卫视播出的由张鲁一、聂远等人主演的电视剧《前行者》,讲述了在二十世纪三十年代初,因叛徒出卖,我上海地下党组织遭到严重破坏,革命事业陷入一片白色恐怖之中。我党情报员马天目刚从法国归来,临危…...
Spring Boot基础教学:创建第一个Spring Boot项目
使用Spring Initializr生成项目 Spring Initializr是一个在线工具,用于快速生成Spring Boot项目的基本结构。以下是使用Spring Initializr创建项目的步骤: 步骤1:访问Spring Initializr 打开网址 start.spring.io。 步骤2:选择…...
基于SpringBoot+Vue实现校园多媒体信息共享平台
作者简介:Java领域优质创作者、CSDN博客专家 、CSDN内容合伙人、掘金特邀作者、阿里云博客专家、51CTO特邀作者、多年架构师设计经验、多年校企合作经验,被多个学校常年聘为校外企业导师,指导学生毕业设计并参与学生毕业答辩指导,…...
WebRTC API分析
主题 本文详细描述常用的webrtc api 媒体协商类 myPeerConnection.createOffer([options]); var options { offerToReceiveAudio: true, // 告诉另一端,你是否想接收音频,默认true offerToReceiveVideo: true, // 告诉另一端&a…...
ArkTS学习笔记:ArkTS起步
ArkTS是HarmonyOS的主力应用开发语言,基于TypeScript扩展,强化了静态检查和分析,旨在提升程序稳定性和性能。它采用静态类型,禁止运行时改变对象布局,并对UI开发框架能力进行扩展,支持声明式UI描述和自定义…...
spring-gateway网关聚合swagger实现多个服务接口切换
前提条件 微服务已经集成了swagger,并且注册进了nacos。 gateway配置 package com.zmy.springcloud.config;import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springfra…...
基于大模型的 UI 自动化系统
基于大模型的 UI 自动化系统 下面是一个完整的 Python 系统,利用大模型实现智能 UI 自动化,结合计算机视觉和自然语言处理技术,实现"看屏操作"的能力。 系统架构设计 #mermaid-svg-2gn2GRvh5WCP2ktF {font-family:"trebuchet ms",verdana,arial,sans-…...
ES6从入门到精通:前言
ES6简介 ES6(ECMAScript 2015)是JavaScript语言的重大更新,引入了许多新特性,包括语法糖、新数据类型、模块化支持等,显著提升了开发效率和代码可维护性。 核心知识点概览 变量声明 let 和 const 取代 var…...
进程地址空间(比特课总结)
一、进程地址空间 1. 环境变量 1 )⽤户级环境变量与系统级环境变量 全局属性:环境变量具有全局属性,会被⼦进程继承。例如当bash启动⼦进程时,环 境变量会⾃动传递给⼦进程。 本地变量限制:本地变量只在当前进程(ba…...
【Java学习笔记】Arrays类
Arrays 类 1. 导入包:import java.util.Arrays 2. 常用方法一览表 方法描述Arrays.toString()返回数组的字符串形式Arrays.sort()排序(自然排序和定制排序)Arrays.binarySearch()通过二分搜索法进行查找(前提:数组是…...
前端倒计时误差!
提示:记录工作中遇到的需求及解决办法 文章目录 前言一、误差从何而来?二、五大解决方案1. 动态校准法(基础版)2. Web Worker 计时3. 服务器时间同步4. Performance API 高精度计时5. 页面可见性API优化三、生产环境最佳实践四、终极解决方案架构前言 前几天听说公司某个项…...
如何在看板中体现优先级变化
在看板中有效体现优先级变化的关键措施包括:采用颜色或标签标识优先级、设置任务排序规则、使用独立的优先级列或泳道、结合自动化规则同步优先级变化、建立定期的优先级审查流程。其中,设置任务排序规则尤其重要,因为它让看板视觉上直观地体…...
【位运算】消失的两个数字(hard)
消失的两个数字(hard) 题⽬描述:解法(位运算):Java 算法代码:更简便代码 题⽬链接:⾯试题 17.19. 消失的两个数字 题⽬描述: 给定⼀个数组,包含从 1 到 N 所有…...
376. Wiggle Subsequence
376. Wiggle Subsequence 代码 class Solution { public:int wiggleMaxLength(vector<int>& nums) {int n nums.size();int res 1;int prediff 0;int curdiff 0;for(int i 0;i < n-1;i){curdiff nums[i1] - nums[i];if( (prediff > 0 && curdif…...
srs linux
下载编译运行 git clone https:///ossrs/srs.git ./configure --h265on make 编译完成后即可启动SRS # 启动 ./objs/srs -c conf/srs.conf # 查看日志 tail -n 30 -f ./objs/srs.log 开放端口 默认RTMP接收推流端口是1935,SRS管理页面端口是8080,可…...
Cinnamon修改面板小工具图标
Cinnamon开始菜单-CSDN博客 设置模块都是做好的,比GNOME简单得多! 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...
