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

Кто вызывает коллбэк onSavedStateHandle

2.0 Middle🔥 101 комментариев
#Android компоненты#Жизненный цикл и навигация

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

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

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

Отличный, очень глубокий и правильный вопрос. Он затрагивает сердце современной архитектуры Android, связывая компоненты ViewModel, SavedStateHandle и жизненный цикл.

Если говорить коротко: коллбэк onSaveInstanceState() (и, следовательно, механизм сохранения состояния в SavedStateHandle) вызывается системой Android (ОС) в строго определённых условиях жизненного цикла активности (Activity) или фрагмента (Fragment).

Давайте разберём всю цепочку вызовов детально, от высокоуровневого триггера до конкретного коллбэка.

Основной принцип и триггер

Система Android вызывает Activity.onSaveInstanceState() (или Fragment.onSaveInstanceState()) перед тем, как уничтожить компонент для освобождения ресурсов, но с намерением восстановить его позже. Классические сценарии:

  • Поворот устройства (смена конфигурации).
  • Переход приложения в фон, когда система может убить процесс для экономии памяти.
  • Переход на другую активность в том же task, когда текущая может быть уничтожена.

Это системный, платформенный вызов. Разработчик не вызывает его напрямую.

Цепочка делегирования от Activity к ViewModel

В современном подходе с ViewModel и SavedStateHandle мы не переопределяем onSaveInstanceState() вручную. Вместо этого мы используем абстракции, которые автоматически интегрируются в этот жизненный цикл. Вот как это работает:

  1. Система -> Activity.onSaveInstanceState(Bundle outState).
    Система вызывает этот метод и предоставляет пустой `Bundle` (`outState`).

  1. Activity -> FragmentManager.saveAllState().
    Активность делегирует сохранение состояния своим фрагментам через `FragmentManager`.

  1. Для каждого Fragment -> Fragment.onSaveInstanceState(Bundle outState).
    Если фрагмент имеет `ViewModel` (через `ViewModelProvider`), `FragmentManager` и система `ViewModel` вступают в сговор.

  1. Ключевое звено: SavedStateViewModelFactory и SavedStateHandleController.
    Когда вы создаёте `ViewModel` с помощью `ViewModelProvider`, и используете стандартную фабрику (или `by viewModels()` в фрагменте), под капотом работает специальный компонент — **`SavedStateViewModelFactory`**. Он создаёт `ViewModel` и привязывает к нему объект **`SavedStateHandle`**.

    В момент вызова `Fragment.onSaveInstanceState()` происходит следующее:

```kotlin
// Упрощённая логика внутри платформы/библиотеки lifecycle-viewmodel-savedstate
override fun onSaveInstanceState(outState: Bundle) {
    super.onSaveInstanceState(outState)
    // Для каждого ViewModel, связанного с этим фрагментом...
    savedStateRegistryController.performSave(outState)
    // ^ Этот вызов проходит через цепочку, в конце которой
    // состояние из SavedStateHandle каждого ViewModel записывается в Bundle.
}
```

5. SavedStateHandle -> Сохранение в Bundle.

    Объект `SavedStateHandle` внутри себя содержит `MutableLiveData` или подобные структуры для ключей, которые вы в него положили (через `set()` или `getLiveData()`). В момент `performSave()` все эти ключи и их **сериализуемые** значения (`String`, `Int`, `Parcelable` и т.д.) записываются в тот самый `Bundle`, который система передала в `onSaveInstanceState()`.

А что с onSavedStateHandle?

Важно уточнить: прямого коллбэка с именем onSavedStateHandle не существует. Возможно, вопрос имел в виду один из двух аспектов:

1. Процесс сохранения состояния в SavedStateHandle

Это не коллбэк, а автоматический процесс, описанный выше. Вы, как разработчик, просто кладёте данные в SavedStateHandle через его методы, и система позже сама их сериализует.

class MyViewModel(savedStateHandle: SavedStateHandle) : ViewModel() {
    init {
        // Сохраняем значение. Оно будет автоматически записано в Bundle.
        savedStateHandle.set("USER_ID_KEY", 12345)

        // Получаем LiveData. Её значение будет автоматически восстановлено из Bundle.
        val userIdLiveData = savedStateHandle.getLiveData<Int>("USER_ID_KEY")
    }
}

2. Процесс восстановления состояния из SavedStateHandle

Когда активность/фрагмент создаётся заново (например, после поворота), система передаёт сохранённый Bundle в метод onCreate().

  • Для Activity: onCreate(savedInstanceState: Bundle?).
  • Для Fragment: onCreate(savedInstanceState: Bundle?).

Далее, при создании ViewModel через ViewModelProvider, SavedStateViewModelFactory принимает этот Bundle, распаковывает его и наполняет данными новый экземпляр SavedStateHandle, который затем передаётся в конструктор ViewModel.

// ViewModel создаётся так:
ViewModelProvider(this, defaultViewModelProviderFactory).get(MyViewModel::class.java)

// Под капотом фабрика делает примерно это:
class SavedStateViewModelFactory(...) {
    fun create(modelClass: String): ViewModel {
        val savedStateHandle = createSavedStateHandle(bundleFromOnCreate) // <-- Бандл здесь!
        return MyViewModel(savedStateHandle) // Передаём хэндл в конструктор
    }
}

Таким образом, в момент создания ViewModel после восстановления, её SavedStateHandle уже содержит все ранее сохранённые значения. Вы можете прочитать их сразу в init блоке или подписаться на LiveData.

Итог

  • Первичный инициатороперационная система Android, управляющая жизненным циклом.
  • Триггер — вызов системой метода onSaveInstanceState() у Activity/Fragment.
  • Механизм — инфраструктура Jetpack (lifecycle-viewmodel-savedstate), которая перехватывает этот вызов, сериализует содержимое всех SavedStateHandle, связанных с компонентом, в системный Bundle, и затем восстанавливает из него при повторном создании.
  • Роль разработчика — использовать SavedStateHandle как чёрный ящик для хранения критических для восстановления данных, не вмешиваясь в ручное управление Bundle. Вся магия происходит автоматически благодаря правильной инициализации ViewModel через ViewModelProvider.