Android onDestroy и Onstop не гарантированно вызываются

В моем приложении для Android (написанном на kotlin) я хотел бы сохранить некоторые данные, когда моя активность будет уничтожена. Но у меня есть проблема. Я провел исследование и обнаружил, что вызов методов onDestroy() и onStop() не гарантируется. Таким образом, практически моя деятельность может быть уничтожена без вызова метода onDestroy(), что было бы для меня катастрофой. Пожалуйста, есть ли у кого-нибудь мягкое решение этой проблемы?

Где вы прочитали, что вызов onStop() не гарантируется?

Bö macht Blau 21.12.2020 21:46

Вот черт. Я только что узнал, что для устройств с версией 4.0 и ниже функция onStop() не гарантируется, а для версий выше 4.0 — да. Хорошо, круто, это практически все устройства :)

user8934776 21.12.2020 21:53

но @BömachtBlau, чем является использование метода onDestroy, если он никогда не будет гарантированно вызван. Я не вижу ни одного сценария, который я бы использовал... Это выглядит так небезопасно, и мне не нравится небезопасность в программировании...

user8934776 21.12.2020 21:54

onDestroy() вызывается, например. когда действие будет уничтожено из-за изменения конфигурации

Bö macht Blau 21.12.2020 21:55

С годами все время от времени меняется — я просто перечитываю это руководство, чтобы быть уверенным, как обстоят дела сегодня.

Bö macht Blau 21.12.2020 21:56

Да, это то, что делает ОС. Но мы, как программисты, никогда не должны переопределять и использовать этот метод, поскольку он небезопасен? Это то, что я имел в виду

user8934776 21.12.2020 21:57

Да конечно. Может быть, когда-нибудь он станет безопасным, как onStop стал безопасным с API 4.0 и выше.

user8934776 21.12.2020 21:57

Хорошо, спасибо за разговор и ваше время, вы мне помогли

user8934776 21.12.2020 21:58

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

Bö macht Blau 21.12.2020 22:01
1
9
845
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вы правы насчет onDestroy()

не рассчитывайте на то, что этот метод будет вызываться как место для сохранения данных!

Для сохранения состояния вы должны использовать onPause(), onSaveInstanceState() или onStop() — вызывается, как только ваша активность больше не видна пользователю.

Ответ принят как подходящий

Некоторая дополнительная информация:

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

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

Я вас понимаю, вы хотите сказать, что лучше всего использовать его, например, для отмены регистрации приемников, слушателей и т. д., чтобы избежать утечек памяти. Это совершенно нормально. Но в Android часто бывают случаи, когда вы должны выполнить какое-то действие, когда Activity уничтожается, и это те случаи, которые меня сбивают с толку. Вы уверены, что единственная причина, по которой onDestroy() не может быть вызвана, заключается в том, что ОС убила все мое приложение?

user8934776 21.12.2020 22:31

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

Tenfour04 21.12.2020 23:56

Но в современных рекомендуемых практиках Android большинство подобных вещей будет в ViewModel. Это одна из причин, по которой я сказал, что переопределение onDestroy() не является обычным явлением. Я не уверен, какие еще вещи вы думаете о том, что может потребоваться сделать, когда действие уничтожено.

Tenfour04 21.12.2020 23:58

Например, в приложении моей компании есть PlayGameActivity, в котором мы запускаем игру. Мы переопределяем метод OnDestroy(), чтобы мы могли вызвать client.refresh() для обновления нашего баланса, когда мы закончим играть в игру и вернемся к другому действию. Так что это не случай «отмены регистрации прослушивателя», но для этого нам все же нужен OnDestroy. Также я хотел бы спросить вас. Если у нас есть фрагмент, правда ли, что мы можем использовать onDetach() в подобных ситуациях (гарантированно ли он вызывается?) и выполнять всю нашу работу здесь.

user8934776 22.12.2020 09:30
onPause и onStop всегда гарантированно вызываются (кроме случаев сбоя). В ситуации нехватки памяти Android может закрыть ваше приложение, когда оно находится в фоновом режиме, поэтому вы не можете полагаться на onDestroy для сохранения чего-либо. Вы никогда не знаете наверняка, когда ваше приложение перейдет в фоновый режим (onStop), что оно вернется без предварительного закрытия, поэтому вы должны предположить, что это может быть, и сохранить в onPause или onStop, чтобы быть уверенным. Я не уверен в гарантиях жизненного цикла фрагмента.
Tenfour04 22.12.2020 15:03

Ооо, так что, когда мое приложение находится в фоновом режиме, а ОС Android отключает его, OnDestroy() не будет вызываться? Теперь я понял, что вы хотите сказать, это проясняет ситуацию. Хорошо, спасибо за ваши объяснения, вы помогли мне разобраться в этом вопросе!

user8934776 22.12.2020 15:33

Другие вопросы по теме