Стандартный подход с использованием ViewModelProvider
, который привязывает ViewModel к жизненному циклу владельца (Activity/Fragment).
class MyViewModel : ViewModel() {
val liveData = MutableLiveData<String>()
}
// В Activity/Fragment:
val viewModel = ViewModelProvider(this).get(MyViewModel::class.java)
Почему так?
ViewModelProvider
гарантирует, что ViewModel переживет изменения конфигурации (например, поворот экрана).Упрощенный синтаксис с Kotlin Property Delegates.
// Для Activity:
val viewModel: MyViewModel by viewModels()
// Для Fragment (с учетом родительского ViewModel):
val viewModel: SharedViewModel by activityViewModels()
Почему так?
ViewModelProvider
).Если ViewModel требует аргументов (например, репозиторий).
class MyViewModel(private val repo: MyRepository) : ViewModel() { ... }
class MyViewModelFactory(private val repo: MyRepository) : ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
return MyViewModel(repo) as T
}
}
// Использование:
val factory = MyViewModelFactory(repository)
val viewModel = ViewModelProvider(this, factory).get(MyViewModel::class.java)
Почему так?
Factory
позволяет передавать параметры, сохраняя жизненный цикл ViewModel.Современный подход с библиотекой Hilt (упрощенный DI от Google).
@HiltViewModel
class MyViewModel @Inject constructor(
private val repo: MyRepository
) : ViewModel() { ... }
// В Activity/Fragment (автоматическое создание):
@AndroidEntryPoint
class MyActivity : AppCompatActivity() {
private val viewModel: MyViewModel by viewModels()
}
Почему так?
Factory
.Сохранение состояния при повороте экрана
ViewModel не уничтожается при изменении конфигурации, в отличие от Activity/Fragment.
Избегание утечек памяти
ViewModel автоматически очищается, когда связанный жизненный цикл (Activity/Fragment) полностью уничтожен (не из-за поворота).
Единый источник истины
Все UI-компоненты (например, несколько Fragments в одной Activity) могут использовать одну ViewModel через activityViewModels()
.
Тестируемость
Паттерн Factory и DI позволяют легко подменять зависимости в тестах.
ViewModelProvider(this).get(MyViewModel::class.java)
.by viewModels()
.ViewModelProvider.Factory
.@HiltViewModel
+ by viewModels()
.