我也遇到了这个问题。 Jon Skeet 的怀疑是正确的,问题是时区的加载效率非常低,打开一个 jar 文件,然后读取清单以尝试获取此信息。
然而,只需调用DateTimeZone.setProvider([custom provider instance ...])
还不够,因为出于对我来说没有意义的原因,DateTimeZone 有一个静态初始化程序,它在其中调用getDefaultProvider()
.
为了完全安全,您可以在调用 joda 中的任何内容之前通过设置此系统属性来覆盖此默认值。
例如,在您的活动中添加以下内容:
@Override
public void onCreate(Bundle savedInstanceState) {
System.setProperty("org.joda.time.DateTimeZone.Provider",
"com.your.package.FastDateTimeZoneProvider");
}
然后你所要做的就是定义FastDateTimeZoneProvider
。我写了以下内容:
package com.your.package;
public class FastDateTimeZoneProvider implements Provider {
public static final Set<String> AVAILABLE_IDS = new HashSet<String>();
static {
AVAILABLE_IDS.addAll(Arrays.asList(TimeZone.getAvailableIDs()));
}
public DateTimeZone getZone(String id) {
if (id == null) {
return DateTimeZone.UTC;
}
TimeZone tz = TimeZone.getTimeZone(id);
if (tz == null) {
return DateTimeZone.UTC;
}
int rawOffset = tz.getRawOffset();
//sub-optimal. could be improved to only create a new Date every few minutes
if (tz.inDaylightTime(new Date())) {
rawOffset += tz.getDSTSavings();
}
return DateTimeZone.forOffsetMillis(rawOffset);
}
public Set getAvailableIDs() {
return AVAILABLE_IDS;
}
}
我已经对此进行了测试,它似乎可以在 Android SDK 2.1+ 和 joda 版本 1.6.2 上运行。它当然可以进一步优化,但是在分析我的应用程序时(mogwee https://market.android.com/details?id=com.mogwee),这将 DateTimeZone 初始化时间从约 500 毫秒减少到约 18 毫秒。
如果您使用 proguard 来构建应用程序,则必须将此行添加到 proguard.cfg 中,因为 Joda 希望类名与您指定的完全相同:
-keep class com.your.package.FastDateTimeZoneProvider