ViewModel сохраняет свое состояние при повороте экрана? Как это возможно? Можете ли предложить, как сделать такой механизм?android-222

Как ViewModel сохраняет состояние

ViewModel переживает изменения конфигурации (например, поворот экрана) благодаря механизму ViewModelStore, который сохраняется системой через onRetainNonConfigurationInstance() (в старых версиях) или ViewModelProvider (в современных реализациях).

Подробный механизм работы

  1. Жизненный цикл ViewModel:

    • Создается при первом запросе (ViewModelProvider.of())
    • Сохраняется при изменении конфигурации
    • Уничтожается только когда полностью завершается host (Activity/Fragment)
  2. Схема сохранения:

    Activity уничтожается → ViewModel сохраняется →
    Новая Activity создается → Получает тот же ViewModel
    

Реализация подобного механизма

Вот как можно реализовать аналогичный функционал:

1. Базовый класс для сохранения состояния

class RetainableManager : ViewModel() {
    private val data = MutableLiveData<String>()

    fun setData(value: String) {
        data.value = value
    }

    fun getData(): LiveData<String> = data
}

2. Кастомная реализация без ViewModel

class StateHolder : RetainableCustomObject() {
    var importantData: String? = null
}

class RetainableCustomObject {
    companion object {
        private var instance: RetainableCustomObject? = null

        fun getInstance(): RetainableCustomObject {
            return instance ?: RetainableCustomObject().also { instance = it }
        }
    }
}

3. Использование в Activity

class MyActivity : AppCompatActivity() {
    private lateinit var stateHolder: StateHolder

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // Получаем существующий или создаем новый
        stateHolder = StateHolder.getInstance()

        if (savedInstanceState == null) {
            // Первая инициализация
            stateHolder.importantData = "Initial Data"
        } else {
            // Восстановление после поворота
            textView.text = stateHolder.importantData
        }
    }
}

Альтернативные подходы

1. Через onRetainNonConfigurationInstance

override fun onRetainCustomNonConfigurationInstance(): Any? {
    return customData // Сохраняем данные
}

// В onCreate():
val data = lastCustomNonConfigurationInstance as? CustomData

2. Используя SavedStateHandle

class MyViewModel(private val savedStateHandle: SavedStateHandle) : ViewModel() {
    val data: LiveData<String> = savedStateHandle.getLiveData("key")

    fun saveData(value: String) {
        savedStateHandle.set("key", value)
    }
}

Почему ViewModel лучше ручной реализации

  1. Интеграция с Lifecycle:

    • Автоматическая очистка ресурсов
    • Корректная работа с жизненным циклом
  2. Поддержка корутин:

    • viewModelScope автоматически отменяется при очистке
  3. Совместимость с Jetpack:

    • Работает с Navigation, Fragments и другими компонентами

Ограничения ViewModel

  1. Не сохраняется при убийстве процесса:

    • Для этого нужно использовать SavedStateHandle
  2. Один ViewModel на scope:

    • Нельзя иметь несколько экземпляров для одной Activity

Резюмируем:

ViewModel сохраняет свое состояние при повороте экрана благодаря системе хранения экземпляров в ViewModelStore. Реализовать подобный механизм можно через синглтон-подход или сохранение объектов в onRetainNonConfigurationInstance, но готовое решение ViewModel предпочтительнее благодаря глубокой интеграции с Android Jetpack и автоматическому управлению жизненным циклом.