← Назад к вопросам

Что будет со состоянием при смене конфигурации?

1.8 Middle🔥 221 комментариев
#Жизненный цикл и навигация#Работа с данными

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Состояние при смене конфигурации в Android

При смене конфигурации (например, поворота экрана, изменения языка, подключения клавиатуры) система Android по умолчанию уничтожает и заново создает Activity. Это приводит к потере текущего состояния UI и данных, если не предпринять специальных мер. Процесс происходит так:

  1. onPause(), onStop(), onDestroy() вызываются для текущего экземпляра Activity.
  2. Создается новый экземпляр Activity.
  3. Вызываются 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: Сохраняются, так как хранятся на диске.

Рекомендации по архитектуре

  1. Используйте ViewModel + LiveData/StateFlow для хранения UI-состояния.
  2. Сохраняйте минимальные данные в Bundle (идентификаторы, простые флаги).
  3. Избегайте хранения тяжелых объектов (Bitmap, контексты) в Bundle или ViewModel.
  4. Для навигации используйте Navigation Component с SavedStateHandle, который сохраняет состояние аргументов.
class MyViewModel(savedStateHandle: SavedStateHandle) : ViewModel() {
    val state: MutableStateFlow<String> = savedStateHandle.getStateFlow("key", "")
}

Таким образом, современный подход предполагает комбинацию ViewModel (для данных в памяти) и onSaveInstanceState (для критичного UI-состояния), что обеспечивает плавный пользовательский опыт при смене конфигурации.

Что будет со состоянием при смене конфигурации? | PrepBro