📅  最后修改于: 2023-12-03 15:06:12.799000             🧑  作者: Mango
在 Android 开发中,ViewModel 组件是一个非常强大和有用的工具,它可以帮助我们将 UI 逻辑和数据逻辑分离,并能够在设备旋转、配置更改等情况下保持数据的状态。不过,在使用 ViewModel 的时候,我们可能会用到 ViewModelProviders 类,但是,最近 Google 工程师已经不推荐使用这个类了。
ViewModelProviders 类的确是一个非常方便的工具,但是它存在一些问题。
首先,ViewModelProviders 是一个静态类,这意味着它会持有 Activity 或 Fragment 实例的引用,这就导致了内存泄漏的风险。当页面被销毁时,ViewModelProviders 可能还会持有这个实例,因此,如果你持有了一个过期的 Activity 或 Fragment,那么调用 ViewModelProviders 将导致内存泄漏。
其次,ViewModelProviders 不支持 Dagger2 依赖注入框架。Dagger2 是一个非常流行的依赖注入框架,但是,由于 ViewModelProviders 是一个静态类,无法使用 Dagger2 注入实例。
最后,ViewModelProviders 也不利于单元测试。由于 ViewModelProviders 是一个静态类,我们无法使用依赖注入来模拟这个实例,从而在单元测试中使用 ViewModels 变得比较困难。
由于 ViewModelProviders 存在上述问题,那么我们应该如何使用 ViewModel 呢?
我们可以使用 ViewModelProvider.Factory 接口来创建 ViewModel 实例,这个接口可以支持 Dagger2 依赖注入,并且不会持有 Activity 或 Fragment 实例的引用,从而避免了内存泄漏的问题。
以下是一个使用 ViewModelProvider.Factory 接口创建 ViewModel 的示例:
class MyViewModel @Inject constructor(private val dataSource: DataSource) : ViewModel() {
// ...
}
class MyViewModelFactory @Inject constructor(private val dataSource: DataSource) : ViewModelProvider.Factory {
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
return modelClass.getConstructor(DataSource::class.java).newInstance(dataSource)
}
}
class MyActivity : AppCompatActivity() {
@Inject lateinit var viewModelFactory: ViewModelProvider.Factory
override fun onCreate(savedInstanceState: Bundle?) {
// ...
val viewModel = ViewModelProviders.of(this, viewModelFactory).get(MyViewModel::class.java)
// ...
}
}
不推荐使用 ViewModelProviders 类,因为它存在内存泄漏、不支持 Dagger2 以及不利于单元测试等问题。我们可以使用 ViewModelProvider.Factory 接口来创建 ViewModel 实例,这是一个更好的方法。