Безопасно ли делать всю очистку в onDestroy?

Более конкретно: безопасно ли размещать отмену задачи в onDestroy? Кроме того, безопасно ли использовать onDestroy для отмены регистрации получателей и освобождения ресурсов?

Моя цель - убедиться, что моя задача отменяется/уничтожается при уничтожении Activity, но не раньше.

при уничтожении():

  1. вызывается, когда активность уничтожается и ресурсы должны быть освобождены.
  2. НЕ вызывается, когда активность уничтожается в спешке (когда в системе мало ресурсов и т. д.).

Первый случай понятен: всю очистку делаю в onDestroy и проблем не возникает. А вот со вторым случаем проблема. Когда действие уничтожается, а onDestroy пропускается (поэтому я не отменяю свою задачу), может ли случиться так, что задание продолжает выполнение, затем завершается и пытается обновить мертвое действие, поэтому приложение вылетает?


Мы подходим к реальному вопросу:

  1. Когда действие уничтожается, а onDestroy пропускается, все, что связано с этим действием, автоматически уничтожается? (Пропускается ли onDestroy только в случае, что все будет полностью уничтожено? Задачи, зарегистрированные приемники и т. д.)
  2. Если onDestroy пропущен, означает ли это, что все приложение уничтожается?

Давайте сосредоточимся на onDestroy(), потому что решение не в onPause() или onStop(). Аргументы:

  • onStop() может быть пропущен при уничтожении Activity, как и onDestroy
  • onPause вызывается слишком рано и слишком часто, поэтому он не подходит для данного варианта использования. Примеры:

Блокировка экрана: onPause можно вызывать, когда экран устройства заблокирован. Очень часто это происходит как заставка и пользователь сразу разблокируется, потому что стоит и смотрит на экран. Отмена задач и остановка всего, что делает мое приложение, в таком случае только ухудшит работу пользователя. Я не хочу, чтобы мое приложение зависало и плохо себя вело только из-за случайной «заставки».

В примере приложения у меня есть два экрана, которые являются действиями. Пользователь может быстро переключаться между ними. В этом приложении пользователи склонны часто и быстро переключать экраны.

Навигация: на одном из экранов есть карта, которая получает обновления местоположения от системы. Он записывает точный графический журнал изменений местоположения (маршрута), поэтому его необходимо запускать постоянно, пока действие не будет закрыто. Обычно я регистрирую и отменяю регистрацию любых получателей в onResume и onPause. Однако это сделало бы приложение очень непригодным для использования, так как обновления на карте будут останавливаться каждый раз, когда пользователь уходит. Поэтому я хотел бы отменить регистрацию получателей в onDestroy.

Список загрузки. На втором экране есть список, в котором показаны данные из веб-службы. Загрузка данных занимает 4 секунды. Я использую AsyncTask и знаю, что должен отменить его при необходимости. Его не следует отменять в onPause, потому что он должен продолжать загружаться, пока пользователь переключается между экранами. Поэтому я хотел бы отменить его в onDestroy.

Примеров может быть еще много. Некоторые из них могут быть не совсем подходящими, по мнению всех (вы можете даже предложить использовать сервис вместо AsyncTask). Но идея важна, и все они имеют одну и ту же идею: продолжать выполнять работу, относящуюся к действию, в то время как действие приостановлено, но УБЕДИТЬСЯ, чтобы прекратить выполнение это происходит, когда действие уничтожается. (Неважно, использую ли я AsyncTask или службу. В любом случае работа должна быть остановлена ​​при уничтожении действия.)

P.S. Если ответ заключается в том, что выполнять очистку в onDestroy небезопасно, это будет означать, что платформа Android требует от нас остановить все, что мы делаем в onPause. И тогда я бы не видел смысла использовать onDestroy...


person Stan    schedule 29.01.2013    source источник


Ответы (3)


Я хотел бы отослать вас к этому ребенку: http://developer.android.com/reference/android/content/ComponentCallbacks2.html#onTrimMemory%28int%29

По сути, это дает вам все места, где система считает полезным отменить задачи и очистить свою память:

Пожалуйста, внимательно рассмотрите следующие 2 случая:

TRIM_MEMORY_UI_HIDDEN — процесс показывал пользовательский интерфейс и больше не показывает его.

TRIM_MEMORY_COMPLETE — процесс приближается к концу списка фоновых LRU.

Каковы случаи для большинства из того, что вы просили.

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

Этот метод сделал мою жизнь разработки намного лучше в подобных случаях.

person Community    schedule 28.04.2014
comment
Спасибо, я не уверен, что смогу напрямую применить это к моему делу, но это, безусловно, выглядит интересно. - person Stan; 09.05.2014

Если вам просто нужно выполнить некоторую очистку, независимо от того, как закрыта активность, вы сможете использовать комбинацию onSaveInstanceState() и onDestroy(). Один из них должен быть назван в любом случае. Возможно, в вашей деятельности есть boolean cleanupDone, который устанавливается всякий раз, когда заканчивается одно из двух.

Относительно сохранения пользовательских данных см. Сохранение постоянного состояния:

Гугл предлагает

пользовательская модель "редактировать на месте"

То есть: сохранить, как только пользователь создаст новые данные, самое позднее в onPause(). Это не означает, что вам нужно воссоздать данные в onResume(), просто их нужно было сохранить.

Кстати: onStop() можно пропустить только на устройствах до Honeycomb, то есть по состоянию на июнь 2015 г., менее 6% всех устройств. Тем не менее, onSaveInstanceState() следует вызывать, если onDestroy() или onStop() опущены.

person serv-inc    schedule 26.06.2015

Насколько я ушел с Android,

1 Когда ваше приложение дает сбой, все связанные с ним ресурсы уничтожаются.

2 Когда устройство меняет конфигурацию, что приводит к уничтожению и воссозданию Activity.

3 Когда приложения, работающие в фоновом режиме, и Android завершают работу из-за нехватки памяти

кроме них, вызывается другой метод обратного вызова i e

1, когда появляется другое действие или ваше устройство блокируется ..и т. д.

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

person Vipin Sahu    schedule 29.01.2013
comment
Спасибо за ваш ответ, но проблема в том, что onDestroy не всегда вызывается при уничтожении активности, особенно если речь идет о нехватке памяти. Итак, как я могу убедиться, что я выпускаю все тогда? Вот о чем мой вопрос. (примечание о 2 - действие воссоздается, но старый экземпляр будет сохранен, если вы сохраните ссылку на него.) - person Stan; 29.01.2013
comment
вещи, которые запускаются в UI-Thread, уничтожаются, а другие сохраняются, например, Ur own Thread, Asyntask, сервисы. - person Vipin Sahu; 29.01.2013