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 确保时间逻辑的准确性。

相关推荐
橙子199110161 小时前
在 Kotlin 中什么是委托属性,简要说说其使用场景和原理
android·开发语言·kotlin
androidwork1 小时前
Kotlin Android LeakCanary内存泄漏检测实战
android·开发语言·kotlin
笨鸭先游2 小时前
Android Studio的jks文件
android·ide·android studio
gys98952 小时前
android studio开发aar插件,并用uniapp开发APP使用这个aar
android·uni-app·android studio
H309192 小时前
vue3+dhtmlx-gantt实现甘特图展示
android·javascript·甘特图
像风一样自由2 小时前
【001】renPy android端启动流程分析
android·gitee
千里马学框架4 小时前
重学安卓14/15自由窗口freeform企业实战bug-学员作业
android·framework·bug·systrace·安卓framework开发·安卓窗口系统·自由窗口
xianrenli3810 小时前
android特许权限调试
android
*拯12 小时前
Uniapp Android/IOS 获取手机通讯录
android·ios·uni-app
天天打码14 小时前
Lynx-字节跳动跨平台框架多端兼容Android, iOS, Web 原生渲染
android·前端·javascript·ios