Различные системные операции Android могут повлиять на состояние вашего фрагмента. Чтобы гарантировать сохранение состояния пользователя, платформа Android автоматически сохраняет и восстанавливает фрагменты и задний стек. Поэтому вам необходимо убедиться, что любые данные в вашем фрагменте также сохранены и восстановлены.
В следующей таблице описаны операции, которые приводят к потере состояния фрагмента, а также сохраняются ли различные типы состояния после этих изменений. В таблице указаны следующие типы состояний:
- Переменные: локальные переменные во фрагменте.
- Состояние представления: любые данные, принадлежащие одному или нескольким представлениям во фрагменте.
- SavedState: данные, присущие этому экземпляру фрагмента, которые следует сохранить в
onSaveInstanceState()
. - NonConfig: данные, полученные из внешнего источника, например сервера или локального репозитория, или созданные пользователем данные, которые отправляются на сервер после фиксации.
Часто переменные обрабатываются так же, как и SavedState , но в следующей таблице проводится различие между ними, чтобы продемонстрировать влияние различных операций на каждую из них.
Операция | Переменные | Просмотр состояния | Саведстате | Неконфигурируемый |
---|---|---|---|---|
Добавлено в задний стек | ✓ | ✓ | х | ✓ |
Изменение конфигурации | х | ✓ | ✓ | ✓ |
Процесс смерти/воссоздания | х | ✓ | ✓ | ✓* |
Удален, не добавлен в задний стек | х | х | х | х |
Хост завершен | х | х | х | х |
* Состояние NonConfig можно сохранить после смерти процесса с помощью модуля Saved State для ViewModel .
Таблица 1. Различные операции по разрушению фрагментов и их влияние на различные типы состояний.
Давайте рассмотрим конкретный пример. Рассмотрим экран, который генерирует случайную строку, отображает ее в TextView
и предоставляет возможность редактировать строку перед отправкой ее другу:
В этом примере предположим, что как только пользователь нажимает кнопку редактирования, приложение отображает представление EditText
, в котором пользователь может редактировать сообщение. Если пользователь нажимает CANCEL , представление EditText
должно быть очищено, а его видимость установлена на View.GONE
. Для обеспечения бесперебойной работы такого экрана может потребоваться управление четырьмя частями данных:
Данные | Тип | Тип государства | Описание |
---|---|---|---|
seed | Long | Неконфигурируемый | Семя, используемое для случайного создания нового доброго дела. Создается при создании ViewModel . |
randomGoodDeed | String | Сохраненное состояние + переменная | Генерируется при первом создании фрагмента. randomGoodDeed сохраняется, чтобы гарантировать, что пользователи увидят одно и то же случайное доброе дело даже после смерти и воссоздания процесса. |
isEditing | Boolean | Сохраненное состояние + переменная | Логический флаг устанавливается в значение true , когда пользователь начинает редактирование. isEditing сохраняется, чтобы гарантировать, что редактируемая часть экрана останется видимой при воссоздании фрагмента. |
Отредактированный текст | Editable | Состояние просмотра (принадлежит EditText ) | Отредактированный текст в представлении EditText . Представление EditText сохраняет этот текст, чтобы гарантировать, что текущие изменения пользователя не будут потеряны. |
Таблица 2: Указывает, что приложение генератора случайного текста должно управлять.
В следующих разделах описывается, как правильно управлять состоянием ваших данных с помощью разрушительных операций.
Посмотреть состояние
Представления отвечают за управление своим состоянием. Например, когда представление принимает вводимые пользователем данные, представление несет ответственность за сохранение и восстановление этих вводимых данных для обработки изменений конфигурации. Все представления, предоставляемые платформой Android, имеют собственную реализацию onSaveInstanceState()
и onRestoreInstanceState()
, поэтому вам не нужно управлять состоянием представления внутри фрагмента.
Например, в предыдущем сценарии отредактированная строка хранится в EditText
. EditText
знает значение отображаемого текста, а также другие детали, такие как начало и конец любого выделенного текста.
Представлению необходим идентификатор, чтобы сохранять свое состояние. Этот идентификатор должен быть уникальным внутри фрагмента и его иерархии представлений. Представления без идентификатора не могут сохранять свое состояние.
<EditText android:id="@+id/good_deed_edit_text" android:layout_width="match_parent" android:layout_height="wrap_content" />
Как упоминалось в таблице 1, представления сохраняют и восстанавливают свое ViewState
посредством всех операций, которые не удаляют фрагмент или не уничтожают хост.
SavedState
Ваш фрагмент отвечает за управление небольшими объемами динамического состояния, которые являются неотъемлемой частью функционирования фрагмента. Вы можете сохранить легко сериализуемые данные, используя Fragment.onSaveInstanceState(Bundle)
. Подобно Activity.onSaveInstanceState(Bundle)
данные, которые вы помещаете в пакет, сохраняются при изменениях конфигурации, а также смерти и воссоздании процесса и доступны в onCreate(Bundle)
вашего фрагмента, onCreateView(LayoutInflater, ViewGroup, Bundle)
и onViewCreated(View, Bundle)
методы.
Продолжая предыдущий пример, randomGoodDeed
— это документ, который отображается пользователю, а isEditing
— это флаг, определяющий, показывает или скрывает фрагмент EditText
. Это сохраненное состояние следует сохранить с помощью onSaveInstanceState(Bundle)
, как показано в следующем примере:
Котлин
override fun onSaveInstanceState(outState: Bundle) { super.onSaveInstanceState(outState) outState.putBoolean(IS_EDITING_KEY, isEditing) outState.putString(RANDOM_GOOD_DEED_KEY, randomGoodDeed) }
Ява
@Override public void onSaveInstanceState(@NonNull Bundle outState) { super.onSaveInstanceState(outState); outState.putBoolean(IS_EDITING_KEY, isEditing); outState.putString(RANDOM_GOOD_DEED_KEY, randomGoodDeed); }
Чтобы восстановить состояние в onCreate(Bundle)
извлеките сохраненное значение из пакета:
Котлин
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) isEditing = savedInstanceState?.getBoolean(IS_EDITING_KEY, false) randomGoodDeed = savedInstanceState?.getString(RANDOM_GOOD_DEED_KEY) ?: viewModel.generateRandomGoodDeed() }
Ява
@Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (savedInstanceState != null) { isEditing = savedInstanceState.getBoolean(IS_EDITING_KEY, false); randomGoodDeed = savedInstanceState.getString(RANDOM_GOOD_DEED_KEY); } else { randomGoodDeed = viewModel.generateRandomGoodDeed(); } }
Как указано в таблице 1, обратите внимание, что переменные сохраняются, когда фрагмент помещается в стек. Обращение с ними как с сохраненным состоянием гарантирует, что они сохранятся при всех разрушительных операциях.
Неконфигурируемый
Данные NonConfig следует размещать за пределами фрагмента, например, в ViewModel
. В приведенном выше примере seed
(наше состояние NonConfig) генерируется в ViewModel
. Логика поддержания его состояния принадлежит ViewModel
.
Котлин
public class RandomGoodDeedViewModel : ViewModel() { private val seed = ... // Generate the seed private fun generateRandomGoodDeed(): String { val goodDeed = ... // Generate a random good deed using the seed return goodDeed } }
Ява
public class RandomGoodDeedViewModel extends ViewModel { private Long seed = ... // Generate the seed private String generateRandomGoodDeed() { String goodDeed = ... // Generate a random good deed using the seed return goodDeed; } }
Класс ViewModel
по своей сути позволяет данным сохраняться при изменении конфигурации, например повороте экрана, и оставаться в памяти, когда фрагмент помещается в задний стек. После смерти и воссоздания процесса ViewModel
создается заново и создается новое seed
. Добавление модуля SavedState
в вашу ViewModel
позволяет ViewModel
сохранять простое состояние даже при прекращении и воссоздании процесса.
Дополнительные ресурсы
Дополнительные сведения об управлении состоянием фрагмента см. в следующих дополнительных ресурсах.
Кодлабы
- Лаборатория разработки компонентов с учетом жизненного цикла
Путеводители
- Модуль сохраненного состояния для модели представления
- Сохранение состояний пользовательского интерфейса