在 Kotlin 中,by viewModels() 和 by viewModels { } 都是用来在 Activity 或 Fragment 中获取 ViewModel 实例的属性委托。它们之间的区别在于是否传递自定义的 ViewModelProvider.Factory:
by viewModels(): 使用默认的 ViewModelProvider.Factory,通常,这个默认工厂会使用 ViewModel 的无参构造函数来创建 ViewModel 实例。- 如果 ViewModel 没有参数,或者使用了依赖注入(如 Hilt)来提供 ViewModel,可以使用这种形式;
by viewModels {...}: 花括号内是一个 Lambda,用于提供自定义的 ViewModelProvider.Factory。当 ViewModel 需要参数时使用,必须提供自定义的 Factory 来创建 ViewModel 实例;
使用指南:
- 如果 ViewModel 不需要外部参数:使用
by viewModel(); - 如果 ViewModel 需要参数或依赖:使用
by viewModels { customFactory }; - 如果使用 Hilt/Dagger 等 DI 框架:使用
by viewModels()(框架自动处理);
添加依赖:
kotlin
dependencies {
// 必需:ViewModel 核心
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.7.0"
// 必需:Activity 或 Fragment 的委托支持(二选一或都选)
implementation "androidx.activity:activity-ktx:1.8.2" // Activity 中使用
implementation "androidx.fragment:fragment-ktx:1.6.2" // Fragment 中使用
}
例如:假设我们有一个需要参数的 ViewModel:
kotlin
class MyViewModel(private val repository: MyRepository) : ViewModel() {
// ...
}
那么,在 Activity 或 Fragment 中,我们需要提供一个 Factory 来创建 MyViewModel:
kotlin
private val viewModel: MyViewModel by viewModels {
object : ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
// 假设我们已经有了MyRepository的实例
return MyViewModel(myRepository) as T
}
}
}
或者,你可以定义一个 ViewModelFactory 类:
kotlin
class MyViewModelFactory(private val repository: MyRepository) : ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
if (modelClass.isAssignableFrom(MyViewModel::class.java)) {
@Suppress("UNCHECKED_CAST")
return MyViewModel(repository) as T
}
throw IllegalArgumentException("Unknown ViewModel class")
}
}
然后,在委托属性中使用:
kotlin
private val viewModel: MyViewModel by viewModels {
MyViewModelFactory(myRepository)
}