Когда фрагмент заменяется и помещается в задний стек (или удаляется), остается ли он в памяти?
Автор вопроса: cottonBallPawsОтветов: 4
Поведение похоже на то, как работают Activity? Например, с Activity это работает так:
Действие A запускает Действие B, пока B отображается на экране, система может удалить A из памяти, если это нужно системе. При нажатии НАЗАД A будет воссоздан в памяти, как если бы он никогда не покидал ее.
Я искал четкое объяснение того, что происходит с памятью с фрагментами, и ничего не нашел. Это работает так же? Например:
Действие C содержит фрагмент F в макете. Затем в какой-то момент F заменяется фрагментом G, но F остается в своем заднем стеке.
Будет ли F оставаться в памяти до тех пор, пока C не будет уничтожен, или он может быть удален системой по мере необходимости?
На самом деле я спрашиваю, есть ли у меня риск нехватки памяти, если у меня есть задний стек сложных фрагментов в одном действии?
Обратите внимание, что ваше первое предположение неверно: действие A никогда не будет удалено из памяти. См. commonsware.com/blog. /2011/10/03/ Thierry-Dimitri Roy 01.03.2012
@Thierry-DimitriRoy, невероятно... Я чувствую, что живу во лжи... Я почти не верю в это... cottonBallPaws 04.03.2012
Система не убивает ни одного действия или фрагмента. Он может только убить весь процесс, чтобы восстановить память, когда она заканчивается. stdout 02.04.2019
Именно так фрагменты хранятся в заднем стеке. Обратите внимание на живую ссылку, там не используются ни WeakReference, ни SoftReference.
Теперь это: FragmentManagerImpl.mBackStack
Именно здесь менеджер хранит задний стек. Простой ArrayList, а также никаких WR или SR.
И, наконец, это: Activity.mFragments
Это ссылка на менеджер фрагментов.
Сборщик мусора может собирать только объекты, которые не имеют активных ссылок (не доступны ни из одного потока). Это означает, что пока ваша активность не будет уничтожена (и поэтому ссылка FragmentManager не исчезнет), GC не сможет собрать ни один из фрагментов в заднем стеке.
Обратите внимание, что при уничтожении Activity и сохраняет состояние (например, когда вы переводите устройство в ландшафтный режим), он не сохраняет фактические Fragment объектов в стеке, только их состояния - Fragment.FragmentState, т. е. фактические фрагменты в обратном стеке воссоздаются каждый раз, когда действие воссоздается с сохраненным состоянием.
Надеюсь это поможет.
PS Итак, вкратце: Да, вы можете исчерпать память, добавив Fragments в задний стек, а также добавив слишком много представлений для представления иерархии.
UPD Учитывая ваш пример, F останется в памяти, пока C не будет убит. Если C убит, а затем воскрес с другой конфигурацией, F также будет уничтожен и реинкарнирован в другом объекте. Таким образом, объем памяти F сохраняется до тех пор, пока C не потеряет состояние или не будет очищен задний стек.
Ответ 2 · рейтинг 7 · Beowulf Bjornson
Прошу прощения за то, что не смог предоставить вам какой-либо официальный источник информации, но мне тоже было любопытно посмотреть, что произойдет, и я решил проверить это. И, согласно моим тестам, да, есть риск нехватки памяти.
Мне пришлось добавить невероятное количество фрагментов (более сотни) в цикл for, чтобы произошло OutOfMemoryError, но это произошло. И проверив свои журналы, я увидел, что методы onCreate() и onCreateView() вызывались много раз, а onSaveInstance(), onPause() и onDestroy вообще не вызывались.
Для справки, вот как я добавил фрагменты в стопку:
Фрагменты, которые я добавил, были довольно простыми: ImageView, EditText, пара TextViews, SeekBar и ListView.
Но если вы не храните в памяти огромное количество данных, это не должно быть проблемой.
Позже я попытался добавить только 50 в задний стек, уничтожив приложение и перезапустив его. И, как я надеялся/догадывался, все фрагменты были восстановлены (и вызваны методы onSaveInstance() и onPause()), поэтому моя реализация жизненного цикла не была проблемой, вызвавшей срабатывание OutOfMemoryError.
Ответ 3 · рейтинг 4 · Bill Gary
Из developer.android.com/guide/topics/fundamentals/fragments.html.
Фрагмент всегда должен быть встроен в действие, и жизненный цикл фрагмента напрямую зависит от жизненного цикла основного действия. Например, когда активность приостановлена, все фрагменты в ней тоже, а когда активность уничтожена, все фрагменты тоже. Однако во время выполнения действия (оно находится в состоянии возобновленного жизненного цикла) вы можете независимо манипулировать каждым фрагментом, например добавлять или удалять их. Когда вы выполняете такую фрагментарную транзакцию, вы также можете добавить ее в резервный стек, управляемый действием - каждая запись обратного стека в действии является записью произошедшей транзакции фрагмента. Задний стек позволяет пользователю отменить транзакцию фрагмента (перейти назад), нажав кнопку НАЗАД.
Ответ 4 · рейтинг 1 · Sid
Да, у вас может не хватить памяти, создавая слишком много фрагментов в одном действии. Фрагменты будут уничтожены только тогда, когда содержащее их действие будет уничтожено.