SimpleDateFormat занимает слишком много времени, когда включен часовой пояс - PullRequest
7 голосов
/ 16 января 2012

Я использую этот простой формат даты

    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.

Как я могу использовать простой формат даты, но чтобы ускорить процесс, я не хочу брать ~ 150 мс за каждое преобразование ...

У кого-нибудь была эта проблема раньше?

Ответы [ 2 ]

10 голосов
/ 16 января 2012

Это связано с отложенной инициализацией строк часового пояса. Только первый звонок займет это много времени. Если SimpleDateFormat используется снова после этого, это загружается из кеша и больше не должен занимать так много времени.

До того, как это было изменено, это было сделано, когда класс был загружен и, таким образом, начало активность заняла эти 2-3 секунды дольше. Это оказало гораздо худшее влияние на пользователя опыт, чем если бы это займет те секунды, когда он на самом деле используется в первый раз. проблема в том, что сейчас нет способа обойти эту проблему из-за дизайна интерфейса SimpleDateFormat. Только более быстрые телефоны могут исправить это, просто принимая меньше время собирать эти строки.

Кэширование происходит в DateFormatSymbols, который использует SimpleDateFormat. От повторное использование этого экземпляра можно загрузить только один раз (для такая же лола). Вы также можете создать этот экземпляр в потоке при запуске активность, так что он уже кешируется, как только он используется. Чтобы начать строки просто позвоните .hashCode (), который принудительно инициализирует кеш. Немного быстрее, но не так просто быть для сериализации экземпляра. Это также вызывает инициализацию кэша.

Тем временем рассмотрите возможность использования AsyncTask для «разогрева» SimpleDateFormat в вашем процессе, прежде чем он вам понадобится. Просто проанализируйте некоторую дату в AsyncTask doInBackground (), чтобы заставить ее загружать часовые пояса когда-нибудь, когда это не сильно повлияет на пользователя. После инициализации в вашем процессе SimpleDateFormat будет работать быстро, пока ваш процесс не будет остановлен.

4 голосов
/ 27 августа 2012

Это не так в последних выпусках Android (и по тексту сообщения журнала я могу сказать, что вы работаете со старым выпуском; современные выпуски сообщают вам, сколько времени было потрачено на icu4c по сравнению с управляемым кодом). Обратите внимание, что ответ от «Пулкит Гоял» был скопирован и вставлен из http://code.google.com/p/android/issues/detail?id=3147, а текст относится к Пончик . Я переписывал этот код несколько раз с тех пор. В настоящее время en_US и локаль системы по умолчанию (во время загрузки) кэшируются в zygote. Существует дополнительный кэш для каждого приложения, поэтому за другие языки вы должны платить только один раз.

В современных выпусках наихудший случай - когда пользователь меняет локаль системы по умолчанию. Потребуется перезапуск zygote («перезапуск во время выполнения» или перезагрузка), чтобы получить строки часового пояса новой локали по умолчанию, кэшированные в zygote, где они могут быть использованы совместно. (Я описал это поведение в комментарии 11 об ошибке, и она поставляется с ICS.)

...