System.currentTimeMillis()与elapsedRealtime()区别

System.currentTimeMillis()SystemClock.elapsedRealtime() 在 Android 开发中用于不同的时间测量场景,核心区别在于它们的底层实现和对系统时间变化的敏感度。以下是详细说明和代码示例:


1. System.currentTimeMillis()

  • 定义:返回自 1970 年 1 月 1 日 UTC 以来的毫秒数(Unix 时间戳)。
  • 特点
    • 受系统时间设置影响(用户或网络时间同步可能导致时间跳变)。
    • 设备休眠时不会递增。
  • 适用场景:需要与真实时间相关的操作,如记录事件时间、生成日期字符串等。

代码示例:记录事件时间戳

java 复制代码
// 记录用户点击事件的时间
long clickTime = System.currentTimeMillis();
saveToDatabase("User clicked at " + clickTime);

// 将时间戳转换为可读日期
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault());
String dateStr = sdf.format(new Date(clickTime));
Log.d("EventTime", "点击时间: " + dateStr);

2. SystemClock.elapsedRealtime()

  • 定义:返回自设备启动以来经过的毫秒数(包括深度休眠时间)。
  • 特点
    • 不受系统时间设置影响。
    • 设备休眠时仍会累计时间。
  • 适用场景:测量时间间隔(如性能统计、倒计时),需稳定不受系统时间干扰的场景。

代码示例:测量代码执行时间

java 复制代码
// 开始计时
long startTime = SystemClock.elapsedRealtime();

// 模拟耗时操作(如下载文件)
new Thread(() -> {
    try {
        Thread.sleep(2000); // 模拟 2 秒操作
    } catch (InterruptedException e) {
        e.printStackTrace();
    }

    // 计算实际耗时
    long endTime = SystemClock.elapsedRealtime();
    long duration = endTime - startTime;
    Log.d("Performance", "操作耗时: " + duration + " 毫秒");
}).start();

错误用法示例

错误:使用 System.currentTimeMillis() 计算耗时

java 复制代码
long start = System.currentTimeMillis();
// 假设用户在此期间调整了系统时间
Thread.sleep(5000); // 实际耗时 5 秒
long end = System.currentTimeMillis();
long wrongDuration = end - start; // 可能得到负数或极大值

正确:使用 SystemClock.elapsedRealtime()

java 复制代码
long start = SystemClock.elapsedRealtime();
Thread.sleep(5000);
long end = SystemClock.elapsedRealtime();
long correctDuration = end - start; // 始终准确为 ~5000 毫秒

总结对比表

特性 System.currentTimeMillis() SystemClock.elapsedRealtime()
时间基准 Unix 时间戳(1970 年) 设备启动后经过的时间
系统时间敏感 ✔️(用户修改时间会影响结果) ❌(结果稳定,不受时间设置影响)
休眠时递增 ❌(休眠时暂停) ✔️(持续计时,包括休眠)
典型用途 日历事件、日志时间戳 性能统计、倒计时、间隔测量

高级场景:跨进程时间同步

在需要跨组件(如 ServiceActivity)同步时间的场景中,elapsedRealtime() 更可靠。例如,音乐播放器显示播放进度:

java 复制代码
// Service 中记录播放开始时间
long playbackStartTime = SystemClock.elapsedRealtime();

// Activity 中实时计算已播放时长
long currentElapsed = SystemClock.elapsedRealtime();
long playbackDuration = currentElapsed - playbackStartTime;
updateUI("已播放: " + playbackDuration + " 毫秒");

通过理解两者的差异,可以在不同场景中选择合适的 API 确保时间逻辑的准确性。

相关推荐
DogDaoDao3 小时前
Android 硬件编码器参数完全指南:MediaCodec 深度解析
android·音视频·视频编解码·h264·硬编码·视频直播·mediacodec
JohnnyDeng944 小时前
Android 自定义 View:Canvas 绘图与事件分发深度解析
android
Android小码家7 小时前
Framework之Launcher小窗开发
android·framework·虚拟屏·小窗
赏金术士7 小时前
第七章:状态管理实战与架构总结
android·ui·kotlin·compose
颂love8 小时前
MySQL的执行流程
android·数据库·mysql
云起SAAS13 小时前
抖音小游戏源码 - 消消乐 | 含激励广告+成就系统 | 开箱即用商业级消除游戏模板
android·游戏·广告联盟·看激励广告联盟流量主·抖音小游戏源码 - 消消乐
大貔貅喝啤酒14 小时前
基于Windows下载安装Android Studio 3.3.2版本教程(2026详细图文版)
android·java·windows·android studio
程序员码歌14 小时前
OpenSpec 到 Superpowers:AI 编码从说清到做对
android·前端·人工智能
2501_9151063214 小时前
深入解析无源码iOS加固原理与方案,保护应用安全
android·安全·ios·小程序·uni-app·cocoa·iphone
黄林晴18 小时前
重磅官宣:Android UI 开发正式进入 Compose-first 时代
android·google io