Выпускать ресурсы в onPause вместо onDestroy

Речь идет о POST-сотовом (то есть Android 3.0+), а приведенные ниже цитаты взяты из https://developer.android.com/reference/android/app/Activity.html

Согласно жизненному циклу, onStop и onDestroy являются гибкими, это означает:

Обратите внимание на столбец «Killable» в приведенной выше таблице – для тех методов, которые отмечены как подлежащие уничтожению, после того, как этот метод возвращает процесс, принимающий эту активность, может быть убит системой в любое время без выполнения другой строки исполняемого кода

  1. Другими словами, onStop (наряду с другими, которые происходят перед этим событием) гарантированно будет вызван, но в тот момент, когда метод возвращается, процесс может умереть, поэтому onDestroy не гарантируется .

    Другая цитата гласит:

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

    С последующим

    Таким образом, активность находится в состоянии killable , например, после onPause () до начала onResume ().

  2. Но это не соответствует тому, что было сказано выше, если только это не соответствует PRE-сотам . Это не относится к POST-сотам , верно? Поэтому в принципе, как onPause, так и onStop гарантированно будут вызваны.

  3. Предполагая, что я только выпущу ресурс в onDestroy, это может привести к возможной утечке, так как onDestroy не может быть вызван, правильно?

  4. Однако может ли этот сценарий (т. Е. OnDestroy не вызываться) произойти, кроме того, когда процесс уничтожается самим андроидом? Существуют ли какие-либо другие сценарии, которые вызывают onDestroy не называться, тем самым утечка ресурса .

  5. Это правда, что, когда Android убивает процесс, что ресурсы будут уничтожены, и утечка не может произойти (даже если мы явно не выпустили ресурс?).

Просьба представить подробную информацию о том, являются ли эти утверждения (1) (2) (3) (4) (5) правильными или нет.

Solutions Collecting From Web of "Выпускать ресурсы в onPause вместо onDestroy"

Прежде всего, давайте поймем, что происходит с документацией, которую вы цитировали.

Следующие команды показывают вывод git blame файла Activity.java в AOSP:

 $ cd $AOSP/frameworks/base $ git blame ./core/java/android/app/Activity.java 

Соответствующая часть выпуска:

 9066cfe98 (The Android Open Source Project 2009-03-03 19:31:44 -0800 363) * <p>Note the "Killable" column in the above table -- for those methods that 9066cfe98 (The Android Open Source Project 2009-03-03 19:31:44 -0800 364) * are marked as being killable, after that method returns the process hosting the 9066cfe98 (The Android Open Source Project 2009-03-03 19:31:44 -0800 365) * activity may killed by the system <em>at any time</em> without another line 9066cfe98 (The Android Open Source Project 2009-03-03 19:31:44 -0800 366) * of its code being executed. Because of this, you should use the 9066cfe98 (The Android Open Source Project 2009-03-03 19:31:44 -0800 367) * {@link #onPause} method to write any persistent data (such as user edits) 9066cfe98 (The Android Open Source Project 2009-03-03 19:31:44 -0800 368) * to storage. In addition, the method 9066cfe98 (The Android Open Source Project 2009-03-03 19:31:44 -0800 369) * {@link #onSaveInstanceState(Bundle)} is called before placing the activity 9066cfe98 (The Android Open Source Project 2009-03-03 19:31:44 -0800 370) * in such a background state, allowing you to save away any dynamic instance 9066cfe98 (The Android Open Source Project 2009-03-03 19:31:44 -0800 371) * state in your activity into the given Bundle, to be later received in 550116576 (RoboErik 2014-07-09 15:05:53 -0700 372) * {@link #onCreate} if the activity needs to be re-created. 9066cfe98 (The Android Open Source Project 2009-03-03 19:31:44 -0800 373) * See the <a href="#ProcessLifecycle">Process Lifecycle</a> 9066cfe98 (The Android Open Source Project 2009-03-03 19:31:44 -0800 374) * section for more information on how the lifecycle of a process is tied 9066cfe98 (The Android Open Source Project 2009-03-03 19:31:44 -0800 375) * to the activities it is hosting. Note that it is important to save 9066cfe98 (The Android Open Source Project 2009-03-03 19:31:44 -0800 376) * persistent data in {@link #onPause} instead of {@link #onSaveInstanceState} 5c40f3fcc (Daisuke Miyakawa 2011-02-15 13:24:36 -0800 377) * because the latter is not part of the lifecycle callbacks, so will not 9066cfe98 (The Android Open Source Project 2009-03-03 19:31:44 -0800 378) * be called in every situation as described in its documentation.</p> 9066cfe98 (The Android Open Source Project 2009-03-03 19:31:44 -0800 379) * 0aae2d4e0 (Dianne Hackborn 2010-12-07 23:51:29 -0800 380) * <p class="note">Be aware that these semantics will change slightly between 0aae2d4e0 (Dianne Hackborn 2010-12-07 23:51:29 -0800 381) * applications targeting platforms starting with {@link android.os.Build.VERSION_CODES#HONEYCOMB} 0aae2d4e0 (Dianne Hackborn 2010-12-07 23:51:29 -0800 382) * vs. those targeting prior platforms. Starting with Honeycomb, an application 0aae2d4e0 (Dianne Hackborn 2010-12-07 23:51:29 -0800 383) * is not in the killable state until its {@link #onStop} has returned. This 0aae2d4e0 (Dianne Hackborn 2010-12-07 23:51:29 -0800 384) * impacts when {@link #onSaveInstanceState(Bundle)} may be called (it may be 0aae2d4e0 (Dianne Hackborn 2010-12-07 23:51:29 -0800 385) * safely called after {@link #onPause()} and allows and application to safely 0aae2d4e0 (Dianne Hackborn 2010-12-07 23:51:29 -0800 386) * wait until {@link #onStop()} to save persistent state.</p> 0aae2d4e0 (Dianne Hackborn 2010-12-07 23:51:29 -0800 387) * 9066cfe98 (The Android Open Source Project 2009-03-03 19:31:44 -0800 388) * <p>For those methods that are not marked as being killable, the activity's 9066cfe98 (The Android Open Source Project 2009-03-03 19:31:44 -0800 389) * process will not be killed by the system starting from the time the method 9066cfe98 (The Android Open Source Project 2009-03-03 19:31:44 -0800 390) * is called and continuing after it returns. Thus an activity is in the killable 9066cfe98 (The Android Open Source Project 2009-03-03 19:31:44 -0800 391) * state, for example, between after <code>onPause()</code> to the start of 9066cfe98 (The Android Open Source Project 2009-03-03 19:31:44 -0800 392) * <code>onResume()</code>.</p> 

Обратите внимание, что абзац, в котором обсуждается поведение после сотовой связи, был добавлен Дайанн Хакборн в 2010-12-07, тогда как прилагаемые абзацы датируются 2009-03-03.

То, что он говорит нам, заключается в том, что Дайан добавила новый абзац, не обновляя остальную часть джавадока, поэтому противоречие. К сожалению, это не редкость в Android.

На ваши вопросы:

1) На постсоветных версиях Android onResume() оба onResume() и onStop() будут вызваны (как заявляет Dianne Hackborn в ее дополнении к javadoc активности).

2) На пре-Honeycomb onPause() только onPause() будет вызван (как указано в более ранней версии javadoc Activity)

3,4,5) onDestroy() не будет вызываться, только если процесс, на котором onDestroy() все приложение, будет убит. Когда процесс уничтожается, все ресурсы, выделенные ему, освобождаются, поэтому в этом случае нет риска утечки памяти.

Важное замечание : поскольку освобождение ресурсов в onDestroy() не приведет к утечке памяти, может показаться хорошей идеей поставить весь «освобождающий» код там. Однако это редко оптимальный подход. Зачем? Читай ниже.

Когда Activity переходит в фоновый режим, он останавливается, но не уничтожается (обычно). Activity может оставаться в этом «остановленном» состоянии довольно долгое время и снова будет запущена, если пользователь вернется в приложение. Если вы выпустите ресурсы в onDestroy() , который не вызывается по умолчанию, когда Activity переходит в фоновый режим, Activity будет удерживать эти ресурсы в состоянии остановки, что приведет к тому, что ваше приложение будет потребляться большим количеством ресурсов в фоновом состоянии.

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

Кроме того, мы, разработчики, должны убедиться, что мы создаем лучшие приложения для наших пользователей. Приложение, которое потребляет не минимальное количество ресурсов телефона пользователя и аккумулятора в фоновом режиме, не является хорошим приложением. И пользователи узнают об этом!

Поэтому я настоятельно рекомендую высвободить все ресурсы в onStop() . Обычно я не переписываю onDestroy() в Activities и Fragments вообще.

Следствие. Как отметил @Juan в своем комментарии, вышеупомянутое важное примечание имеет не менее важное, но не столь очевидное следствие: onStart() должен быть единственным методом распределения ресурсов. Независимо от вашего определения «ресурсов», ни onCreate() ни onResume() должны выделять эти ресурсы.

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

  1. Это правда, что, когда Android убивает процесс, что ресурсы будут уничтожены, и утечка не может произойти (даже если мы явно не выпустили ресурс?).

Ответ зависит от того, чего именно вы боитесь. Как отметил Василий, Android (основанный на Linux) – это современная безопасная ОС, которая гарантирует, что когда процесс будет убит, вся память будет выпущена, причем все открытые файлы, сетевые соединения и т. Д. Также будут правильно закрыты. Таким образом, утечки ресурсов в обычном смысле не будет.

Тем не менее существует один потенциально проблематичный сценарий. Предположим, что у вас есть какая-то логика, которую вы выполняете, когда вы выпускаете какой-то ресурс, то есть что-то, что вы поместили бы в деструктор на C ++ или в реализацию Closeable.close в Java. Например, у вас есть кеш в памяти, который задерживает запись в файл с пакетной загрузкой. Обычно вы onDestroy кеш-память в onDestroy и все работает нормально. Но когда процесс принудительно убит Android, onDestroy может не вызываться, и ваша логика onDestroy не выполняется, и поэтому вы можете потерять некоторые данные и / или иметь недопустимое состояние в своем постоянном хранилище. Поэтому, если у вас есть что-то подобное, вы должны обеспечить согласованность, выполнив такую ​​логику в более надежном месте: onPause или onStop .