当包含时区时,SimpleDateFormat 花费的时间太长
我正在使用这个简单的日期格式,
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS Z");
问题是当我使用它时,转换时间需要太长时间,在 logcat 中我看到类似这样的内容
I/Resources( 4284): Loaded time zone names for en in 272ms.
I/Resources( 4284): Loaded time zone names for en in 194ms.
I/Resources( 4284): Loaded time zone names for en in 112ms.
I/Resources( 4284): Loaded time zone names for en in 111ms.
I/Resources( 4284): Loaded time zone names for en in 113ms.
I/Resources( 4284): Loaded time zone names for en in 127ms.
I/Resources( 4284): Loaded time zone names for en in 253ms.
I/Resources( 4284): Loaded time zone names for en in 110ms.
I/Resources( 4284): Loaded time zone names for en in 154ms.
I/Resources( 4284): Loaded time zone names for en in 112ms.
How can I use simple date formater but to speed the thing up,我不想每次转换约 150 毫秒...
以前有人遇到过这个问题吗?
I am using this simple date format
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS Z");
the problem is when I use this it takes too long to convert the time, in logcat I see something like this
I/Resources( 4284): Loaded time zone names for en in 272ms.
I/Resources( 4284): Loaded time zone names for en in 194ms.
I/Resources( 4284): Loaded time zone names for en in 112ms.
I/Resources( 4284): Loaded time zone names for en in 111ms.
I/Resources( 4284): Loaded time zone names for en in 113ms.
I/Resources( 4284): Loaded time zone names for en in 127ms.
I/Resources( 4284): Loaded time zone names for en in 253ms.
I/Resources( 4284): Loaded time zone names for en in 110ms.
I/Resources( 4284): Loaded time zone names for en in 154ms.
I/Resources( 4284): Loaded time zone names for en in 112ms.
How can I use simple date formater but to speed the things up, I do not want to take ~150ms for every conversion...
Does anybody had this problem before ?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这是由于时区字符串的延迟初始化造成的。只有第一个
打电话要花这么长时间。如果之后再次使用 SimpleDateFormat
从缓存加载,不应该再花那么长时间了。
在更改之前,它是在加载类并因此开始时完成的
一项活动需要多花 2-3 秒的时间。这对用户造成了更严重的影响
与第一次实际使用时花费的几秒钟相比,体验会更好。这
问题是,由于设计原因,目前无法规避此问题
SimpleDateFormat API 的。只有更快的手机才能通过更少的时间来解决这个问题
是时候收集这些字符串了。
缓存发生在 SimpleDateFormat 正在使用的 DateFormatSymbols 中。经过
重用该实例可能只需要加载一次(对于
相同的地方)。您还可以在启动时在线程中创建该实例
活动,以便一旦使用它就已经被缓存。要初始化字符串只需调用
.hashCode() 强制初始化缓存。更快一点但不太简单
是序列化实例。这也强制缓存被初始化。
在此期间,请考虑在需要之前使用 AsyncTask 在流程中“预热”SimpleDateFormat。只需解析 AsyncTask doInBackground() 中的某些日期即可使其在不会对用户产生太大影响的某个时间加载时区。一旦在进程中初始化,SimpleDateFormat 将快速运行,直到进程终止。
This is due to the lazy initialization of the timezone zone strings. Only the first
call will take this long. If the SimpleDateFormat is used again afterwards it's
loaded from cache and shouldn't take that long anymore.
Before this was changed it was done when the class was loaded and thus the start of
an activity took those 2-3 seconds longer. This had a much worse impact on the user
experience than if it takes those seconds when it's actually used the first time. The
problem is that there's no way right now to circumvent this issue due to the design
of the SimpleDateFormat api. Only faster phones might fix this by just taking less
time to collect those strings.
The caching happens in the DateFormatSymbols that SimpleDateFormat is using. By
reusing that instance it's possible to only have to load the stings once (for the
same loale). You could also create that Instance in a thread at the startup of the
activity so that it's already cached once it's used. To init the strings just call
.hashCode() which does force initialize the cache. A bit faster but less simple would
be to serialize the instance. This also forces the cache to be initialized.
In the interim, consider using AsyncTask to "warm up" SimpleDateFormat in your process before you need it. Just parse some date in the AsyncTask doInBackground() to get it to load the timezones sometime when it will not impact the user so much. Once initialized in your process, SimpleDateFormat will run quickly until your process is terminated.
在最新版本的 Android 上情况并非如此(从日志消息的文本中我可以看出您正在运行旧版本;现代版本告诉您在 icu4c 与托管代码上花费了多少时间)。请注意,“Pulkit Goyal”的答案是从 http:// /code.google.com/p/android/issues/detail?id=3147,文本指的是“Donut”。从那时起我已经多次重写了这段代码。目前,en_US 和系统的默认语言环境(在启动时)缓存在 zygote 中。每个应用程序都有一个进一步的缓存,因此对于其他区域设置,您只需支付一次。
现代版本中最糟糕的情况是用户更改系统的默认区域设置。需要重新启动 zygote(“运行时重新启动”或重新启动)才能将新的默认语言环境的时区字符串缓存在可以共享的 zygote 中。 (我在 bug 的评论 11 中描述了这种行为,它是随 ICS 一起提供的。)
This isn't true on recent releases of Android (and from the text of the log message I can tell that you're running an old release; modern releases tell you how much time was spent in icu4c versus managed code). Note that the answer from "Pulkit Goyal" was copy and pasted from http://code.google.com/p/android/issues/detail?id=3147 and the text refers to Donut. I've rewritten this code several times since then. Currently, en_US and the system's default locale (at boot time) are cached in the zygote. There's a further per-app cache so that for other locales you should only pay once.
The worst case in modern releases is where the user changes the system's default locale. It would require a restart of the zygote (a "runtime restart" or a reboot) to get the new default locale's time zone strings cached in the zygote where they could be shared. (i described this behavior in comment 11 on the bug, and it's shipped with ICS.)