當在Android系統中切換語言時,會帶來一個有趣的bug:SimpleDateFormat在處理“z”時區字段時會花費很長的時間。如果你在一個ListView裡多次調用這個方法,就會發現這個ListView在滾動時很不流暢。控制臺相關輸出如下所示:
view plaincopy to clipboardprint?
I/Resources( 471): Loaded time zone names for en_US in 1904ms.
I/Resources( 471): Loaded time zone names for en_US in 1400ms.
I/Resources( 471): Loaded time zone names for en_US in 1260ms.
I/Resources( 471): Loaded time zone names for en_US in 1360ms.
I/Resources( 471): Loaded time zone names for en_US in 1232ms.
I/Resources( 471): Loaded time zone names for en_US in 1344ms.
I/Resources( 471): Loaded time zone names for en_US in 1228ms.
I/Resources( 471): Loaded time zone names for en_US in 1904ms.
I/Resources( 471): Loaded time zone names for en_US in 1400ms.
I/Resources( 471): Loaded time zone names for en_US in 1260ms.
I/Resources( 471): Loaded time zone names for en_US in 1360ms.
I/Resources( 471): Loaded time zone names for en_US in 1232ms.
I/Resources( 471): Loaded time zone names for en_US in 1344ms.
I/Resources( 471): Loaded time zone names for en_US in 1228ms.
這是因為時區字段在Android系統中是被設計為延遲初始化的,隻有在第一次使用到時才會去獲取,並保存在緩存中,隨後都會從這個緩存中去獲取。但是根據之前SimpleDateFormat API的設計,沒有方法來達到這個目的。在Android官方issues裡也反復提到瞭這個問題,從2009年被發現到現在,都始終沒有解決。
在期待Android系統修復這個問題或者越來越快的系統硬件支持之外,基本很難處理這個系統原生的bug,但是我們可以通過一個簡單的辦法來改進這個問題。核心的思路就是緩存時區帶來的偏移值。我們隻需要在第一次加載時獲取這個偏移值並存儲,然後在以後每一次根據這個偏移值算出真實的時間值,代碼如下:
view plaincopy to clipboardprint?
public static long cachedTime = -1;
public static long mtimeToLong(String time) {
SimpleDateFormat format = new SimpleDateFormat(
“yyyy-MM-dd HH:mm:ss.SSS”); // 獲取沒有時區的時間格式
try {
Date date = format.parse(time);
if(cachedTime == -1) { // 第一次取值時
SimpleDateFormat localFormat = new SimpleDateFormat(
“yyyy-MM-dd HH:mm:ss.SSSz”); // 獲取有時區的時間格式
Date localDate = localFormat.parse(time);
long localTime = localDate.getTime();
cachedTime = localTime – date.getTime(); // 計算出差值並存儲
return localTime;
} else { // 第一次之後的取值
return date.getTime() + cachedTime;
}
} catch (ParseException e) {
e.printStackTrace();
return 0;
}
}