Как ведет жизненный цикл фрагмента при изменении конфигурации
Комментарии (2)
Ответ сгенерирован нейросетью и может содержать ошибки
Жизненный цикл фрагмента при изменении конфигурации
При изменении конфигурации устройства (поворот экрана, изменение языка, подключение клавиатуры) Android уничтожает и пересоздает текущую Activity, а вместе с ней и все связанные фрагменты. Этот процесс обеспечивает корректную адаптацию интерфейса к новым условиям, но требует правильной обработки состояния.
Основные этапы жизненного цикла
При повороте экрана фрагмент проходит следующие стадии:
- onPause(), onStop(), onDestroyView() — текущий экземпляр фрагмента останавливается и уничтожает свое представление.
- onDestroy(), onDetach() — фрагмент полностью уничтожается.
- Создается новый экземпляр Activity и фрагмента.
- onAttach(), onCreate() — новый фрагмент инициализируется.
- onCreateView(), onViewCreated() — создается новое представление.
- onStart(), onResume() — фрагмент становится видимым и активным.
Ключевой момент: Сам объект фрагмента уничтожается, но система может автоматически восстановить его состояние через onSaveInstanceState().
Сохранение состояния
Для сохранения временных данных используется Bundle:
class MyFragment : Fragment() {
private var temporaryData: String? = null
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
outState.putString("TEMPORARY_DATA", temporaryData)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
temporaryData = savedInstanceState?.getString("TEMPORARY_DATA")
// Восстановление UI состояния
if (savedInstanceState != null) {
// Восстановление скролл позиции, введенного текста и т.д.
}
}
}
ViewModel как современное решение
ViewModel переживает изменение конфигурации, что делает ее идеальным местом для хранения UI-данных:
class MyFragment : Fragment() {
private val viewModel: MyViewModel by viewModels()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewModel.userData.observe(viewLifecycleOwner) { data ->
// Обновление UI с данными, которые сохранились при повороте
updateUI(data)
}
}
}
class MyViewModel : ViewModel() {
private val _userData = MutableLiveData<String>()
val userData: LiveData<String> = _userData
fun loadData() {
// Данные сохранятся при повороте экрана
_userData.value = "Important UI Data"
}
}
Особенности поведения
- setRetainInstance(true): Устаревший метод, который сохранял экземпляр фрагмента при смене конфигурации. Не рекомендуется к использованию с современной архитектурой Android.
- onConfigurationChanged(): Если Activity обрабатывает конфигурацию самостоятельно, фрагмент не пересоздается:
// В AndroidManifest.xml для Activity
android:configChanges="orientation|screenSize|keyboardHidden"
// В фрагменте
override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig)
// Ручная адаптация к новой конфигурации
adjustLayoutForNewOrientation()
}
Практические рекомендации
- Используйте ViewModel для хранения UI-данных вместо ручного сохранения в Bundle.
- Восстанавливайте состояние в onViewCreated(), а не в onCreateView().
- Разделяйте ответственность:
- ViewModel — для данных
- Сохраненный экземпляр — для минимального состояния UI
- Аргументы фрагмента — для начальных параметров
- Учитывайте жизненный цикл View: Используйте viewLifecycleOwner для LiveData наблюдений во фрагментах:
// Правильно
viewModel.data.observe(viewLifecycleOwner) { data ->
updateUI(data)
}
// Риск утечек памяти при повороте
viewModel.data.observe(this) { data ->
updateUI(data)
}
Распространенные ошибки
- Хранение ссылок на View в ViewModel — приводит к утечкам памяти.
- Восстановление состояния в onCreate() — View еще не создан.
- Игнорирование viewLifecycleOwner — наблюдения продолжаются после уничтожения View.
Правильная обработка жизненного цикла фрагмента при изменении конфигурации критически важна для обеспечения стабильной работы приложения и хорошего пользовательского опыта. Современный подход с использованием ViewModel и LiveData значительно упрощает эту задачу по сравнению с ручным управлением состоянием через Bundle.