Как Android обрабатывает фоновые потоки при выходе из Activity? - PullRequest
30 голосов
/ 10 октября 2010

Мне нужно, чтобы мое приложение для Android сохраняло его состояние на диске, когда его активность переводится в фоновый режим или отключается. Было предложено запустить поток при вызове onPause () и выполнить там любые дорогостоящие процедуры ввода-вывода (см. Быстрое и надежное сохранение / загрузка состояния документа для редактора изображений ).

В каких ситуациях ОС прерывает поток и как часто они возникают?

Я предполагаю, что это будет похоже на то, как обрабатываются действия, когда ОС может произвольно решить уничтожить поток, но в основном это будет делать только тогда, когда ресурсы крайне ограничены. Хотя было бы неплохо найти какую-то конкретную документацию по этому вопросу.

После игры с некоторым тестовым кодом фоновый поток, запущенный в onPause (), будет бесконечно работать в фоновом режиме на моем устройстве (я пытался загрузить много приложений и не смог его убить).

Для моего конкретного приложения я пишу растровый редактор, в котором я использую шаблон Command и шаблон Memento, чтобы разрешить отмену и повтор правок. Я бы хотел, чтобы пользователь мог отменить / повторить свои правки, например, пользователь получает телефонный звонок, и действие прекращается, когда оно помещается в фоновом режиме. Лучшее решение, которое я могу придумать, - это использовать фоновый поток для постоянного сохранения объектов моей команды и сувенира на диске во время использования приложения, а также для завершения сохранения любых объектов, оставленных в фоновом потоке, если вызывается onPause. В худшем случае, если поток будет убит, я потеряю только некоторые правки.

Ответы [ 3 ]

20 голосов
/ 10 октября 2010

В каких ситуациях ОС прерывает поток и как часто они возникают?

ОС не будет уничтожать поток, если только он не убивает процесс - Android ничего не делает с потоками, которые вы создаете сами. Если вы на переднем плане, вас не убьют. Шансы Android убить процесс в течение нескольких секунд после того, как вы потеряли передний план (после onPause()), ничтожны. Документацию по времени жизни процесса - что там есть - можно найти здесь .

4 голосов
/ 10 октября 2010

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

Если вы хотите выполнить фоновую операцию, которая продолжается, даже когда естьэто не передний план, вы почти всегда хотите запустить его внутри Сервиса.С другой стороны, сервис менее вероятно, что будет убит, но нет гарантии, если вы не используете "startForeground".В результате будет отображаться уведомление для пользователя о том, что что-то происходит в фоновом режиме, но, насколько я знаю, это единственный способ запустить асинхронный фоновый поток, который гарантированно не будет уничтожен.

Честно говоря,правильный ответ - убедиться, что нет никакого временного состояния процесса, для сохранения которого потребуется много времени.Если вам нужно написать большой файл, чтобы отразить несколько пользовательских изменений, рассмотрите возможность ведения «журнала транзакций», который вы можете использовать для создания перезапускаемой операции сохранения.Учитывая это, вы можете безопасно запускать свои сохранения в службе и знать, что даже если они будут убиты, они будут автоматически перезапущены, когда станут доступны ресурсы.

1 голос
/ 10 октября 2010

Обычно сохранение состояния в onPause - это правильное решение, если оно выполняется быстро. Я не думаю, что это четко задокументировано, когда процесс убит, но вы иногда видите его в logcat, когда запускаете несколько требовательных приложений (например, после запуска Google Планета Земля и Браузер).

В Android DevTools также есть возможность автоматически уничтожать действия, когда вы уходите от них, хотя это, вероятно, не распространяется на процесс. (DevTools есть на эмуляторе и на некоторых рутованных телефонах).

Я думаю, что ваш подход звучит разумно - используйте поток с низким приоритетом, чтобы постоянно обновлять сохраненные данные, и назначьте ему нормальный приоритет в onPause, и установите флаг в onPause, который говорит, что он завершается после завершения.

Очевидно, что вам нужно убедиться, что у вас не возникнет проблем с синхронизацией, если вы сразу же после onPause попадете в onResume (т. Е. Пока поток все еще занят сохранением).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...