Что будет со состоянием при смене конфигурации?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Состояние при смене конфигурации в Android
При смене конфигурации (например, поворота экрана, изменения языка, подключения клавиатуры) система Android по умолчанию уничтожает и заново создает Activity. Это приводит к потере текущего состояния UI и данных, если не предпринять специальных мер. Процесс происходит так:
onPause(),onStop(),onDestroy()вызываются для текущего экземпляра Activity.- Создается новый экземпляр Activity.
- Вызываются
onCreate(),onStart(),onResume()для нового экземпляра.
Сохранение и восстановление состояния
1. Автоматическое сохранение UI-состояния
Для стандартных View (например, EditText, CheckBox) система автоматически сохраняет и восстанавливает данные, если у них задан android:id. Это работает через механизм onSaveInstanceState() и onRestoreInstanceState().
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
outState.putString("KEY_TEXT", editText.text.toString())
}
override fun onRestoreInstanceState(savedInstanceState: Bundle) {
super.onRestoreInstanceState(savedInstanceState)
editText.setText(savedInstanceState.getString("KEY_TEXT"))
}
2. ViewModel — рекомендованный способ
ViewModel переживает смену конфигурации, так как она привязана к жизненному циклу LifecycleOwner, а не к конкретному экземпляру Activity. Данные в ViewModel сохраняются в памяти.
class MyViewModel : ViewModel() {
val liveData = MutableLiveData<String>()
}
class MyActivity : AppCompatActivity() {
private val viewModel: MyViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
viewModel.liveData.observe(this) { data ->
// Данные сохранятся при повороте
}
}
}
3. Сохранение в Bundle с onRetainCustomNonConfigurationInstance()
Устаревший способ (в FragmentActivity) — использование onRetainCustomNonConfigurationInstance() для сохранения тяжелых объектов (например, загруженных данных).
override fun onRetainCustomNonConfigurationInstance(): Any? {
return myDataObject // Объект будет доступен в следующем экземпляре
}
4. Флаги в манифесте (не рекомендуется)
Можно задать android:configChanges в манифесте, чтобы Activity не пересоздавалась, а получала callback onConfigurationChanged(). Но это антипаттерн, так как требует ручной обработки всех изменений ресурсов.
<activity android:name=".MyActivity"
android:configChanges="orientation|screenSize|keyboardHidden"/>
Что происходит с разными компонентами?
- Fragment с setRetainInstance(true): Сохраняется при смене конфигурации (но устарел, вместо него используют ViewModel).
- LiveData, Flow в ViewModel: Данные сохраняются.
- Статические переменные или синглтоны: Сохраняются, но могут приводить к утечкам памяти.
- Данные в БД или SharedPreferences: Сохраняются, так как хранятся на диске.
Рекомендации по архитектуре
- Используйте ViewModel + LiveData/StateFlow для хранения UI-состояния.
- Сохраняйте минимальные данные в Bundle (идентификаторы, простые флаги).
- Избегайте хранения тяжелых объектов (Bitmap, контексты) в Bundle или ViewModel.
- Для навигации используйте Navigation Component с SavedStateHandle, который сохраняет состояние аргументов.
class MyViewModel(savedStateHandle: SavedStateHandle) : ViewModel() {
val state: MutableStateFlow<String> = savedStateHandle.getStateFlow("key", "")
}
Таким образом, современный подход предполагает комбинацию ViewModel (для данных в памяти) и onSaveInstanceState (для критичного UI-состояния), что обеспечивает плавный пользовательский опыт при смене конфигурации.