2012-05-19 2 views
2

Я использую Intent Service, которая выполняет действие и должна вернуться к активности, которая запустила его в результате действия.Отправлять данные из службы в действие и поворот экрана

Я искал несколько десятков подобных сообщений, но насколько я могу судить, все решения, которые я нашел, имеют проблему. Они не обрабатывают хорошее вращение экрана. Предположим, что действие запускает Intent Service, для выполнения действия служба занимает 10 секунд, и в течение этих 10 секунд экран поворачивается. Активность уничтожается, и создается новая.

  1. Использование приемника: он создает утечку памяти, поскольку приемник связан с деятельностью, которая должна быть уничтожена, поэтому деятельность никогда не уничтожается.
  2. Использование трансляции: вам необходимо зарегистрировать слушателя и незарегистрировать слушателя до того, как действие будет уничтожено. Если широковещательное сообщение поступит после того, как слушатель не зарегистрирован, и до регистрации слушателя новой активности сообщение никогда не будет получено.
  3. Использование сообщений: то же, что и приемник.
  4. Использование общих настроек/базы данных со слушателем: то же, что и для широковещательной передачи.

Решение, с которым я пришел, имеет сервис, сохраняющий результат в файле предпочтений, и регулярную проверку активности (скажем каждые 200 мс) для изменения файла предпочтений. Таким образом, когда экран вращается, действие перестает проверяться и начинается снова при воссоздании. Если результат был поставлен между ними, он все равно попадает на (воссозданную) деятельность. Однако кажется, что это потребляет процессор и выполняет ненужные чтения с SD-карты.

Другим решением будет предоставление услуги сохранить результат в файле/базе данных предпочтений и установить глобальную переменную до момента ее сохранения. В активности есть слушатель файла/базы данных предпочтений. Перед регистрацией слушателя он проверяет глобальную переменную, чтобы увидеть, был ли результат поставлен во время вращения экрана (глобальный var < currentTimeMillies()), и если true, получает результат, если нет, регистрирует слушателя. Поскольку результат может быть поставлен между проверкой и регистрацией, это должно быть сделано внутри блока, в котором активность содержит блокировку, которую служба должна получить, чтобы поместить результат. Это также будет работать, но это слишком сложно.

Есть ли более простой и элегантный способ сделать это, сохранив поворот экрана?

ответ

1

Посмотрите на мой ответ на этот вопрос:

How to handle IPC between a service and an activity (and its subactivity)?

Возможно, это даст вам идею.

EDIT (добавить следующее предложение):

Другой подход будет использовать приемник, который вы создаете в деятельности. При вращении экрана ОС вызовет функциюRetainNonConfigurationInstance(), где вы можете вернуть экземпляр получателя, и он будет передан в новую активность (см. GetLastNonConfigurationInstance()). ПРИМЕЧАНИЕ. Эти методы устарели в 4.0, и вы можете использовать фрагмент и setRetainInstance() для достижения аналогичного поведения.

+0

Мне понравился ответ, на который вы перенаправили меня. Я пошел со вторым решением, которое я написал, используя предпочтения и вообще не глобальную переменную. Проблема в том, что предпочтения не могут сохранять все типы данных (Bundles, Parcelables, BigDecimals и т. Д.), Заставляя меня делать постоянное преобразование из строк и в строки.Ваше решение кажется намного более элегантным, без использования SD-карты, без серьезного потребления памяти (на первый взгляд), все аккуратно и чисто. Я также реализовал базовый класс для связи IntentService. И, кстати, мне нужна совместимость с Android 1.6 (уровень API 4), поэтому я стараюсь не использовать фрагменты, даже с ACL. – cdriver

+0

Рад помочь и рад, что решение сработало для вас! –

Смежные вопросы