1

Я читаю FragmentRetainInstance sample. Существует переменная RetainedFragment mWorkFragment в UiFragment. Итак, как можно удалить UiFragment из памяти после поворота экрана? Насколько я понимаю, mWorkFragment - это ссылка на то, что сохраняется при поворотах экрана и других изменениях конфигурации.Ссылка на сохраненный фрагмент в фрагменте пользовательского интерфейса. Как удалить фрагмент пользовательского интерфейса из памяти после поворота экрана?

Update # 1

я повернул экран и нажал Инициировать GC, а затем прессуют Dump кучу. Я видел, что число UiFragment экземпляров было 1. Почему? Я ожидал увидеть 2: 1 для текущей ориентации и 1 для предыдущей ориентации.

Инициировать GC:

enter image description here

дамп кучи:

enter image description here

+0

'UiFragment' не сохраняется. Если он сохранен, он не будет воссоздан, когда будет восстановлена ​​активность хоста, а именно, как работает «Фрагмент # setRetainInstance (...)». Итак, после поворота экрана и инициализации gc, предыдущий экземпляр 'UiFragment' должен быть собран в мусор. –

+0

* Как удалить UiFragment из памяти * - GC начнется с корня GC (который не экземпляр UiFragment не будет), а затем перейдите к его ссылкам (и так далее), чтобы увидеть, какие объекты по-прежнему нужны. Таким образом, ссылка mWorkFragment не является матерью, потому что нет объекта, который долго жил, имея ссылку на экземпляр UiFragment, чтобы сохранить его в живых. – Luksprog

+0

@Luksprog, насколько я понимаю из вашего комментария, GC обходит объекты, начиная с корня (возможно, класс 'Application'), а затем определяет, что' UiFragment' недоступен (после изменения конфигурации нет ссылок). Поэтому его можно удалить. 'UiFragment' является корнем недостижимого поддерева, а' mWorkFragment' является дочерним элементом 'UiFragment'. Если корень недоступен, все его дети недоступны. Правильно? –

ответ

1

Как я сказал в своем комментарии, то UiFragment от образца вы связаны не утечка. Он действительно содержит ссылку на RetainedFragment, которая выживает при изменении конфигурации, но эта ссылка не имеет значения. GC начнется с корня GC, и оттуда он пересечет объекты, следуя ссылкам, которые он находит внутри объектов. Поскольку UiFragment не ссылается на что-то, что живет (например, RetainedFragment), оно будет находиться за пределами иерархии живых объектов и будет иметь право на сбор мусора.

Если вы хотите увидеть утечку памяти, в образце, к которому вы привязались, удалите строку mProgressBar = null; из inDetach() обратного вызова RetainedFragment. С этим изменением RetainedFragment будет содержать ссылку на UiFragment (на самом деле это старая активность вместе со всеми своими данными), чтобы старый экземпляр Context оставался в живых, по крайней мере до тех пор, пока не будет вызван обратный вызов onActivityCreated() для функции RetainedFragment (внутри onActivityCreated() mProgressBar будет очищен и сделан, чтобы указывать на восстановленный ProgressBar UiFragment).