← Назад к вопросам
Можно ли использовать enum для ограниченного набора состояний?
1.2 Junior🔥 221 комментариев
#Kotlin основы#Архитектура и паттерны
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Как ViewModel остается жить после смерти Activity
ViewModel остаётся жить после destroy Activity благодаря ViewModelStore и ViewModelProvider. ViewModel не уничтожается вместе с Activity при изменении конфигурации (поворот экрана) или других причинах уничтожения Activity. Это критично для сохранения состояния приложения.
Как это работает
// Activity уничтожается и создаётся заново
class MainActivity : AppCompatActivity() {
private val viewModel: MainViewModel by viewModels()
// viewModel живёт дольше Activity!
}
Механизм жизни ViewModel
Activity создаётся → ViewModelStore создаётся
↓
viewModel создаётся (хранится в ViewModelStore)
↓
Activity destroy (конфигурационные изменения)
↓
ViewModelStore ОСТАЁТСЯ живым!
↓
Activity создаётся заново
↓
viewModel достаётся из старого ViewModelStore
↓
Activity destroy (по-настоящему)
↓
ViewModelStore уничтожается → ViewModel.onCleared()
ViewModelStore — ключ к долголетию
ViewModelStore — это компонент, который хранит ViewModel'ки и не привязан напрямую к Activity.
// Внутреннее устройство (упрощённо)
class ViewModelStore {
private val store: MutableMap<String, ViewModel> = mutableMapOf()
fun put(key: String, viewModel: ViewModel) {
store[key] = viewModel
}
fun get(key: String): ViewModel? = store[key]
fun clear() {
for (viewModel in store.values) {
viewModel.clear() // Вызывает onCleared()
}
store.clear()
}
}
ViewModelProvider — фабрика для создания ViewModel
// Когда ты пишешь:
private val viewModel: MainViewModel by viewModels()
// На самом деле происходит:
val viewModel = ViewModelProvider(this)
.get(MainViewModel::class.java)
// ViewModelProvider ищет ViewModel в ViewModelStore:
// 1. Есть ли уже такой ViewModel в хранилище?
// 2. Если да → верни существующий
// 3. Если нет → создай новый и сохрани в ViewModelStore
Где живёт ViewModelStore
// ViewModelStore в ComponentActivity (родитель AppCompatActivity)
open class ComponentActivity : AppCompatActivity {
private var viewModelStore: ViewModelStore? = null
fun getViewModelStore(): ViewModelStore {
if (viewModelStore == null) {
viewModelStore = ViewModelStore()
}
return viewModelStore!!
}
}
Почему ViewModel выживает при поворотах экрана
Когда экран поворачивается:
- Activity уничтожается (onDestroy вызывается)
- Activity создаётся заново (onCreate вызывается)
- НО ViewModelStore НЕ уничтожается!
class MainActivity : AppCompatActivity() {
private val viewModel: MainViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// При повороте экрана:
// Первый раз: viewModel создаётся в ViewModelStore
// Второй раз (после поворота): viewModel достаётся из ViewModelStore
println(viewModel.hashCode()) // Один и тот же объект!
}
}
// Тест
fun testViewModelSurvival() {
val firstHashCode = viewModel.hashCode()
// Поворот экрана (Activity уничтожается и создаётся)
val secondHashCode = viewModel.hashCode()
assertEquals(firstHashCode, secondHashCode) // PASS!
}
Жизненный цикл ViewModel
class MainViewModel : ViewModel() {
init {
println("ViewModel создана") // Один раз при первом создании
}
override fun onCleared() {
println("ViewModel очищена") // Один раз при уничтожении Activity
// Очистка ресурсов, отписка от событий
}
}
// Поворот экрана:
// 1. Activity destroy → onDestroy() Activity
// 2. Activity create → onCreate() Activity
// 3. ViewModel НЕ создаётся заново (выводит только один раз "ViewModel создана")
// 4. Activity destroy (по-настоящему) → onCleared() ViewModel
Сохранение состояния в ViewModel
class MainViewModel : ViewModel() {
private val _uiState = MutableStateFlow("initial")
val uiState: StateFlow<String> = _uiState.asStateFlow()
fun updateState(newState: String) {
_uiState.value = newState
}
}
// Activity
class MainActivity : AppCompatActivity() {
private val viewModel: MainViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// При повороте экрана состояние СОХРАНИТСЯ!
lifecycleScope.launch {
viewModel.uiState.collect { state ->
updateUI(state)
}
}
}
}
Отличие от savedInstanceState
// savedInstanceState — сохраняется в onSaveInstanceState()
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
outState.putString("key", "value")
}
// ViewModel — просто живёт в памяти, не сохраняется на диск
// Поэтому ViewModel ТЕРЯЕТСЯ при:
// 1. Force kill приложения
// 2. Перезагрузка устройства
// 3. Смерть процесса из-за нехватки памяти
// Поэтому используй SavedStateHandle для сохранения на диск:
class MainViewModel(
private val savedStateHandle: SavedStateHandle
) : ViewModel() {
val state: StateFlow<String> = savedStateHandle
.getStateFlow("state", "initial")
}
Когда ViewModel уничтожается
- На повороте экрана — НЕ уничтожается (выживает)
- При Back нажатии — уничтожается (Activity finish)
- При Force Stop приложения — уничтожается
- При нехватке памяти — может быть уничтожена (но ViewModelStore очищается)
// Проверка когда ViewModel уничтожается
class MainViewModel : ViewModel() {
override fun onCleared() {
// Вызывается когда Activity finish (Back нажата)
// ИЛИ Activity полностью уничтожена
super.onCleared()
cleanup()
}
}
Правила работы с ViewModel
- ViewModel = состояние, а не логика
- ViewModel > SavedInstanceState (для простого состояния)
- SavedStateHandle для стойкого сохранения
- onCleared() для очистки ресурсов (отписка, отмена Coroutines)
Ответ: ViewModel живёт дольше Activity благодаря ViewModelStore, которые хранит ViewModel отдельно от жизненного цикла Activity. При поворотах экрана Activity уничтожается, но ViewModelStore остаётся, поэтому ViewModel выживает и переиспользуется.