返回

Android MVVM 中获取上下文:最佳实践

Android

在 Android MVVM 中获取上下文:最佳实践

MVVM(模型-视图-视图模型)是一种软件设计模式,将应用程序的业务逻辑从用户界面(UI)中分离出来。在 Android MVVM 应用程序中,视图模型通常不包含任何 Android 特定的代码,以实现更好的可测试性。然而,有时需要在视图模型中使用上下文,例如从 XML 中获取资源或初始化首选项。本文将探讨在 Android MVVM 视图模型中获取上下文的最佳方法。

方法 1:使用 AndroidViewModel

AndroidViewModel 是 AndroidX 架构组件库提供的一个类,它允许视图模型访问应用程序上下文。虽然这种方法提供了一种简单的方法来访问上下文,但值得注意的是,AndroidViewModel 仍然包含 Android 特定的代码,这可能违背 MVVM 模式的原则。

方法 2:通过构造函数注入

一个更纯正的 MVVM 方法是通过构造函数注入将上下文传递到视图模型。这可以确保视图模型不依赖于 Android 特定的代码,并允许使用 Dagger 或其他依赖项注入框架管理视图模型的生命周期。

示例代码:

class MyViewModel(private val context: Context) {
    // ...
}

在活动或片段中,使用依赖项注入框架(如 Dagger)创建视图模型实例并提供上下文:

// 在 Activity 中
@Inject
lateinit var myViewModel: MyViewModel

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    // 使用 Dagger 注入视图模型
    DaggerMyComponent.create().inject(this)
    // ...
}

方法 3:使用 ViewModelProvider.Factory

ViewModelProvider.Factory 是一个用于创建视图模型实例的接口。我们可以实现此接口,并在创建视图模型时传递上下文:

示例代码:

class MyViewModelFactory(private val context: Context) : ViewModelProvider.Factory {
    override fun <T : ViewModel?> create(modelClass: Class<T>): T {
        if (modelClass.isAssignableFrom(MyViewModel::class.java)) {
            return MyViewModel(context) as T
        }
        throw IllegalArgumentException("Unknown ViewModel class")
    }
}

然后,在活动或片段中使用带有工厂的 ViewModelProvider 创建视图模型实例:

// 在 Fragment 中
val viewModelFactory = MyViewModelFactory(requireContext())
val myViewModel = ViewModelProvider(this, viewModelFactory).get(MyViewModel::class.java)

选择最佳方法

选择哪种方法来获取上下文取决于具体的应用程序需求和 MVVM 实现的严格程度。如果需要访问 Android 特定的代码并且可测试性不是主要关注点,则 AndroidViewModel 是一种简单且方便的方法。如果优先考虑可测试性和 MVVM 模式的纯正性,则通过构造函数注入或 ViewModelProvider.Factory 是更好的选择。

常见问题解答

1. 在 AndroidViewModel 中获取上下文有哪些缺点?

使用 AndroidViewModel 的缺点是它包含 Android 特定的代码,这可能违背 MVVM 模式的原则。

2. 如何通过构造函数注入传递上下文?

通过构造函数注入传递上下文需要在视图模型中定义一个带上下文的构造函数,并在活动或片段中使用依赖项注入框架来创建视图模型实例并提供上下文。

3. 使用 ViewModelProvider.Factory 的优点是什么?

使用 ViewModelProvider.Factory 的优点是它允许在创建视图模型时以一种独立于 Android 代码的方式传递上下文,并支持使用依赖项注入框架。

4. 哪种方法更可测试?

通过构造函数注入或 ViewModelProvider.Factory 获取上下文的方法更可测试,因为它们不依赖于 Android 特定的代码。

5. 我可以在视图模型中获取任何类型的上下文吗?

可以获取特定类型的上下文,如 Activity 上下文或 Fragment 上下文。在通过构造函数注入或 ViewModelProvider.Factory 获取上下文时,需要将正确的上下文类型传递到视图模型。