Розуміння набору фрагментаRetainInstance (булева)


341

Починаючи з документації:

public void setRetainInstance (boolean зберегти)

Контролюйте, чи зберігається екземпляр фрагмента під час відновлення діяльності (наприклад, від зміни конфігурації). Це можна використовувати лише з фрагментами, які не знаходяться в задній стеці. Якщо встановлено, життєвий цикл фрагмента буде дещо іншим при відтворенні діяльності:

  • onDestroy () не буде називатися (але onDetach () все одно буде, тому що фрагмент відривається від його поточної активності).
  • onCreate (пакет) не буде викликаний, оскільки фрагмент не створюється заново.
  • onAttach (Activity) та onActivityCreate (Bundle) все ще будуть називатися.

У мене є кілька питань:

  • Чи збереже фрагмент також свій погляд, чи це буде відтворено при зміні конфігурації? Що саме означає «утримується»?

  • Чи буде зруйнований фрагмент, коли користувач покине діяльність?

  • Чому це не працює з фрагментами на задній стеці?

  • Які випадки використання мають сенс використовувати цей метод?


Відповіді:


348

Перш за все, перегляньте мій пост про збережені фрагменти. Це може допомогти.

Тепер, щоб відповісти на ваші запитання:

Чи зберігає фрагмент також стан перегляду , чи це буде відтворено при зміні конфігурації - що саме "зберігається"?

Так, Fragmentстан буде збережено протягом зміни конфігурації. Зокрема, "збережено" означає, що фрагмент не буде знищений при зміні конфігурації. Тобто, Fragmentзаповіт буде збережено, навіть якщо зміна конфігурації призведе Activityдо знищення основи .

Чи буде зруйнований фрагмент, коли користувач покине діяльність?

Так само, як Activitys, Fragments може бути знищена системою, коли ресурсів пам’яті мало. Незалежно від того, чи зберігають у вас фрагменти стану екземпляра через зміни конфігурації, це ніяк не вплине на те, знищить систему чи ні, як Fragmentтільки ви вийдете з Activity. Якщо ви залишите Activity(тобто, натиснувши кнопку додому), Fragments може бути знищений або не може. Якщо ви покинете кнопку Activity, натиснувши кнопку "назад" (таким чином, викликаючи finish()та ефективно знищуючи Activity), усі Activityприєднані Fragments також будуть знищені.

Чому це не працює з фрагментами на задній стеці?

Ймовірно, є кілька причин, чому це не підтримується, але найбільш очевидною причиною для мене є те, що Activityутримується посилання на FragmentManagerта FragmentManagerкерує backstack. Тобто, незалежно від того, чи захочете ви зберегти свій Fragments чи ні, Activity(і, таким чином FragmentManager, backstack) буде знищено при зміні конфігурації. Ще одна причина, по якій це може не спрацювати, полягає в тому, що речі можуть стати складними, якщо як збережені фрагменти, так і не збережені фрагменти дозволили існувати на одній задній кулі.

Які випадки використання мають сенс використовувати цей метод?

Збережені фрагменти можуть бути дуже корисними для розповсюдження інформації про стан - особливо управління потоками - через випадки діяльності. Наприклад, фрагмент може слугувати хостом для екземпляра Threadабо AsyncTaskкерувати його роботою. Докладнішу інформацію див. У моєму блозі на цю тему.

Взагалі, я б ставився до цього аналогічно до використання onConfigurationChangedз Activity... не використовуйте його як бандаїд тільки тому, що ви занадто ледачий, щоб правильно / керувати зміною орієнтації правильно. Використовуйте його лише тоді, коли вам потрібно.


37
Представлені об’єкти не зберігаються, вони завжди знищуються при зміні конфігурації.
Маркус Юнгінгер

103
Наскільки я можу сказати, якщо у вас є setRetainInstance(true), на Fragmentоб'єкт Java, і весь його вміст НЕ знищені обертання, але вигляд буде відтворений. Тобто onCreatedView()знову називається. Це в основному так, як слід було б працювати з ActivitiesAndroid 1.0. Я не вважаю, що це "лінь" використовувати його, або використовувати його не "належно". Насправді я не можу зрозуміти, чому це не за замовчуванням, або чому ви коли-небудь хочете його вимкнути.
Timmmm

24
Я вважаю ваше пояснення до "Чому це не працює з фрагментами на задній стеці?" важко зрозуміти. Але, можливо, я німий :(
HGPB

13
@dierre Діяльність може бути знищена багатьма способами. Наприклад, якщо натиснути "назад", активність буде знищена. Якщо натиснути "додому", діяльність буде припинено і через деякий час в майбутньому вона може бути знищена, коли пам'ять буде мало. Затримані Fragments зберігаються лише через зміни конфігурації, де основну діяльність потрібно знищити та негайно відтворити. У всіх інших випадках, коли діяльність знищується, також будуть знищені збережені фрагменти.
Алекс Локвуд

3
@AlexLockwood ласка , ви можете підтвердити наступне: Навіть якщо setRetainInstance(true)використовується, один ще повинен реалізувати свою власну наполегливість ( savedInstanceStateабо інакше) , щоб мати можливість обробляти всі сценарії: наприклад , «домашній ключ, поворот, назад в додаток» відтворює мій фрагмент з конструктором виклик, втрачаючи всі змінні стану. Я маю AsyncTaskзмінну члена, тому я хочу зберегти її, тепер, якщо я хочу, щоб вона працювала, я змушена припинити завдання, зберегти стан і відновити, коли користувач повернеться. Отже, загалом, це лише швидкий спосіб допомогти в обертанні, але в іншому випадку марний взагалі.
TWiStErRob

28

setRetaininstanceкорисний лише тоді, коли ваші activityзнищені та відтворені через зміну конфігурації, оскільки екземпляри зберігаються під час дзвінка до onRetainNonConfigurationInstance. Тобто, якщо ви повернете пристрій, збережені фрагменти залишаться там (вони не знищуються та відтворюються.), Але коли час вбивства вбиває активність по відновленню ресурсів, нічого не залишається. При натисканні кнопки "назад" та виходу з активності все знищується.

Зазвичай я використовую цю функцію для збереження орієнтації, що змінюється Time. Скажіть, я завантажив купу Bitmaps з сервера, і кожен з них становить 1 Мб, коли користувач випадково обертає свій пристрій, я, звичайно, не хочу робити всі роботи з завантаження знову. Я створюю свої власні Fragmentрастрові карти і додаю його до менеджера і дзвоню setRetainInstance, всі бітові карти все ще є, навіть якщо орієнтація екрана змінюється.


Чи створюєте ви фрагменти "Тільки для даних" (без будь-якого віджета) лише як власник для ваших растрових зображень чи можуть ці фрагменти також мати віджети? Я читав щось про небезпеку створення витоків пам'яті, коли фрагмент містить щось, що стосується контексту / діяльності ...
hgoebl

Структура буде зрозумілою mActivityдля вас. Але я не знаю, чи буде час виконання також очищати віджети в екземплярі фрагмента в цьому випадку. Спробуйте його або зануриться у вихідний код.
suitianshi

Хороший приклад того, коли ми можемо використовувати setRetainin substance
Mu Sa

12

SetRetainInstance (true) дозволяє сорту фрагменту вижити. Її члени будуть утримуватися під час зміни конфігурації, як обертання. Але це все одно може бути вбито, коли діяльність знищена на задньому плані. Якщо активність, що міститься у фоновому режимі, знищена системою, її instanceState повинна бути збережена системою, якою ви працювали наSaveInstanceState належним чином. Іншим словом завжди буде називатися onSaveInstanceState. Хоча onCreateView не буде викликано, якщо SetRetainInstance є істинним, а фрагмент / активність ще не вбитий, він все одно буде викликаний, якщо він вбитий і намагається повернути його назад.

Ось декілька аналіз андроїд активності / фрагмент сподівання це допомагає. http://ideaventure.blogspot.com.au/2014/01/android-activityfragment-life-cycle.html


8
Я точно бачу, як onCreateView знову викликається на збереженому фрагменті під час обертання екрана.
аїй

Це посилання - ваш власний блог? Ви повинні це зрозуміти, якщо це так.
Flexo

4

setRetainInstance () - застарілий

Як фрагменти версії 1.3.0-alpha01

Метод setRetainInstance () для фрагментів застарілий. З впровадженням ViewModels розробники мають специфічний API для збереження стану, який може бути пов’язаний з Графіками діяльності, фрагментами та навігацією. Це дозволяє розробникам використовувати нормальний, не збережений фрагмент і зберігати окремий стан, який вони хочуть зберігати окремим, уникаючи загального джерела протікань, зберігаючи корисні властивості єдиного створення та руйнування збереженого стану (а саме конструктора ViewModel і зворотний виклик onCleared (), який він отримує).


2

setRetainInstance (булевий) корисний, коли ви хочете мати якийсь компонент, який не прив’язаний до життєвого циклу діяльності. Цей прийом використовується, наприклад, rxloader для "обробки життєвого циклу активності Android для спостережуваного rxjava" (який я тут знайшов ).

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.