Android中各種Time API詳細
1、時間API
為了跟蹤性能,我們需要測量時間間隔,即兩個時間點之間的差異。 JDK 為我們提供了兩種獲取當前時間的方法:
// Milliseconds since Unix epoch (00:00:00 UTC on 1 January 1970) System.currentTimeMillis() // Nanoseconds since the VM started. System.nanoTime()
Android 提供了一個 SystemClock 類,它增加了一些:
// (API 29) Clock that starts at Unix epoch. // Synchronized using the device's location provider. SystemClock.currentGnssTimeClock() // Milliseconds running in the current thread. SystemClock.currentThreadTimeMillis() // Milliseconds since boot, including time spent in sleep. SystemClock.elapsedRealtime() // Nanoseconds since boot, including time spent in sleep. SystemClock.elapsedRealtimeNanos() // Milliseconds since boot, not counting time spent in deep sleep. SystemClock.uptimeMillis()
我們應該選擇哪一個? SystemClock 的 javadoc 有助于回答這個問題:
System#currentTimeMillis 可以由用戶或電話網絡設置,因此時間可能會不可預測地向后或向前跳躍。 間隔或經過時間測量應使用不同的時鐘。
SystemClock#uptimeMillis 在系統進入深度睡眠時停止。 這是大多數間隔計時的基礎,例如 Thread#sleep(long) 、Object#wait(long) 和 System#nanoTime。 當間隔不跨越設備休眠時,該時鐘適用于間隔計時。
SystemClock#elapsedRealtime 和 SystemClock#elapsedRealtimeNanos 包括深度睡眠。 該時鐘是通用間隔計時的推薦基礎。
應用程序的性能對深度睡眠中發(fā)生的事情沒有影響,所以我們最好的選擇是 SystemClock.uptimeMillis() 和 System.nanoTime()
2、uptimeMillis() vs nanoTime()
System.nanoTime() 比 uptimeMillis() 更精確,但這僅對微基準測試有用。 在生產中跟蹤性能時,我們需要毫秒級的分辨率。
讓我們比較一下它們的性能影響。 我克隆了 Android Benchmark Samples 存儲庫并添加了以下測試:
@LargeTest
@RunWith(AndroidJUnit4::class)
class TimingBenchmark {
@get:Rule
val benchmarkRule = BenchmarkRule()
@Test
fun nanoTime() {
benchmarkRule.measureRepeated {
System.nanoTime()
}
}
@Test
fun uptimeMillis() {
benchmarkRule.measureRepeated {
SystemClock.uptimeMillis()
}
}
}
在運行 Android 10 的 Pixel 3 上的結果:
System.nanoTime() 中值時間:208 ns
SystemClock.uptimeMillis() 中值時間:116 ns
SystemClock.uptimeMillis() 幾乎快兩倍! 雖然這種差異應該不會對應用程序產生任何有意義的影響,但我們能弄清楚為什么它要快得多嗎?
3、uptimeMillis() 實現
SystemClock.uptimeMillis() 實現為帶有@CriticalNative 注釋的本機方法。 CriticalNative 為不包含對象的方法提供更快的 JNI 轉換。
public final class SystemClock {
@CriticalNative
native public static long uptimeMillis();
}
原生實現在 SystemClock.c++ 中:
int64_t uptimeMillis()
{
int64_t when = systemTime(SYSTEM_TIME_MONOTONIC);
return (int64_t) nanoseconds_to_milliseconds(when);
}
systemTime() 在 Timers.cpp 中定義:
nsecs_t systemTime(int clock) {
static constexpr clockid_t clocks[] = {
CLOCK_REALTIME,
CLOCK_MONOTONIC,
CLOCK_PROCESS_CPUTIME_ID,
CLOCK_THREAD_CPUTIME_ID,
CLOCK_BOOTTIME
};
timespec t = {};
clock_gettime(clocks[clock], &t);
return nsecs_t(t.tv_sec)*1000000000LL + t.tv_nsec;
}
4、nanoTime() 實現
System.nanoTime() 也被實現為帶有@CriticalNative 注釋的本地方法。
public final class System {
@CriticalNative
public static native long nanoTime();
}
本地實現在 System.c 中:
static jlong System_nanoTime() {
struct timespec now;
clock_gettime(CLOCK_MONOTONIC, &now);
return now.tv_sec * 1000000000LL + now.tv_nsec;
}
這兩個實現其實很相似,都調用clock_gettime() 。
事實證明,@CriticalNative 最近才被添加到 System.nanoTime() ,這就解釋了為什么它變慢了!
結論:
在生產應用中跟蹤性能時:
對于大多數用例,毫秒分辨率就足夠了。 要測量時間間隔,請使用 SystemClock.uptimeMillis() 或 System.nanoTime() 。 后者在較舊的 Android 版本上速度較慢,但這在這里無關緊要。
到此這篇關于Android中各種Time API詳細的文章就介紹到這了,更多相關Android中各種Time API內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Android中用RxJava和ViewPager實現輪播圖
現在App中實現一個輪播圖已經是很多產品的標配了,這篇文章給大家詳細介紹了如何利用RxJava和ViewPager實現輪播圖,有需要的朋友們可以參考借鑒,下面來一起看看吧。2016-09-09
Android 基于MediatorLiveData實現紅點的統一管理
這篇文章主要介紹了Android 基于MediatorLiveData實現紅點的統一管理,幫助大家更好的理解和學習使用Android,感興趣的朋友可以了解下2021-04-04
Android開發(fā)中避免應用無響應的方法(Application Not Responding、ANR)
這篇文章主要介紹了Android開發(fā)中避免應用無響應的方法,即避免彈出Application Not Responding(ANR)對話框,需要的朋友可以參考下2014-06-06
Android Jetpack系列之App Startup使用詳解
這篇文章主要為大家介紹了Android Jetpack系列之App Startup使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-10-10
Java4Android開發(fā)教程(二)hello world!
一般的開發(fā)教程都是介紹完安裝配置開發(fā)環(huán)境,緊接著來一篇hello world,算是國際慣例吧,我們當然也不能免俗,哈哈,各位看官請看好了!2014-10-10
Android Studio自定義萬能注釋模板與創(chuàng)建類,方法注釋模板操作
這篇文章主要介紹了Android Studio自定義萬能注釋模板與創(chuàng)建類,方法注釋模板操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-03-03

