AndroidViewModel与ViewModel的区别

255
随着引入 Android 架构组件库,引入了几个新的类,包括 AndroidViewModelViewModel。然而,我很难弄清楚这两个类之间的区别。文档 简要地描述了 AndroidViewModel

应用程序上下文感知的 ViewModel

我欣赏简洁明了,但这到底意味着什么?我们应该在何时选择使用 AndroidViewModel 而不是 ViewModel,反之亦然?

4个回答

316

AndroidViewModel 提供应用程序上下文

如果您需要在 Viewmodel 内部使用上下文,则应使用 AndroidViewModel(AVM),因为它包含应用程序上下文。 要检索上下文,请调用 getApplication(),否则使用常规 ViewModel(VM)。

AndroidViewModel 具有应用程序上下文。我们都知道,具有静态上下文实例是有问题的,因为这可能会导致内存泄漏! 但是,拥有静态 Application 实例并不像您想象的那么糟糕,因为在运行的应用程序中只有一个 Application 实例。

因此,通常情况下,在特定类中使用和拥有 Application 实例并不是问题。 但是,如果 Application 实例引用它们,则存在引用循环问题,这就是问题所在。

另请参阅Application Instance相关信息

AndroidViewModel 对单元测试有问题

AVM 提供了应用程序上下文,这对于单元测试是有问题的。 单元测试不应涉及任何 Android 生命周期,例如上下文。


50
为什么不总是使用AndroidViewModel呢?即使当前不需要,以后可能会需要上下文。这样做有什么缺点吗? - SamAko
26
如果你查看代码,它通过一个指向Application的字段来扩展ViewModel。如果我不需要它,我不喜欢有一个强制性的构造函数,并带有Application参数(这是AndroidViewModel所要求的),而是更愿意只使用ViewModel。当我将来需要上下文时,我可以轻松地进行更改。 - Boy
5
当您希望在Fragment中使用它或在同一Activity的不同Fragment之间共享ViewModel时,请使用ViewModel - codelearner
25
使用 AndroidViewModel 会依赖于 Context,这会导致无法在普通的单元测试中进行测试,只能使用仪器化测试。我还没有亲自尝试过,这只是一个想法。 - Konrad Morawski
3
AndroidViewModel 和 ViewModel 是相同的,唯一的区别在于 AndroidViewModel 包含应用程序上下文。您可以使用 ViewModel 并将上下文传递给从 MediaStore 加载数据的 ViewModel 函数,或者使用具有应用程序上下文的 AndroidViewModel。 - Alex
显示剩余5条评论

22

终于,我得到了一个更简单的解释,稍微...... AndroidViewModel类是ViewModel的子类,与它们相似,都被设计用来存储和管理与UI相关的数据,并负责准备和提供UI所需的数据,自动允许数据在配置更改时保留。

唯一的区别是AndroidViewModel具有应用程序上下文,如果您需要上下文来获取系统服务或具有类似要求,则这非常有帮助。 粗体字使其更加易懂。


2
官方来源 https://medium.com/androiddevelopers/locale-changes-and-the-androidviewmodel-antipattern-84eb677660d9 - Neeraj Sewani
常规的ViewModel没有访问父上下文的权限吗? - IgorGanapolsky

21

AndroidViewModelViewModel的一个子类。它们之间的区别在于,我们可以传递应用程序上下文,以便在仓库中实例化数据库等需要应用程序上下文的情况下使用。

AndroidViewModel是一个应用程序上下文感知的ViewModel。

AndroidViewModel:

public class PriceViewModel extends AndroidViewModel {
private PriceRepository priceRepository;

public PriceViewModel(@NonNull Application application) {
    super(application);
    priceRepository= new PriceRepository(application);
    allPrices = priceRepository.getAllPrices();
}

视图模型:

public class PriceViewModel extends ViewModel {
public PriceViewModel() {
    super();
}

只有在需要应用程序上下文时,您才应该使用 AndroidViewModel

您不应该在ViewModel中存储对 Activity 或引用 Activity 的视图的引用。因为 ViewModel 设计的目的是要比 Activity 更长久存在,这会导致内存泄漏。


1
Application 的值是从哪里传递过来的?它是通过构造函数从另一个类传递过来的吗? - IgorGanapolsky
1
@IgorGanapolsky 是的,它是通过其抽象化的工厂类传递的。你的起点可能是vm的实例化:by viewmodel。请参考ViewModelProvider.Factory如何操作。还可以查看其源代码:cs.android.com - FalloutBoy

1

除了AndroidViewModel提供给你一个应用程序上下文(application context)的区别,而ViewModel则不提供。你必须理解的重要事情是Google本身推荐使用ViewModel而不是AndroidViewModel

所以,除非真的有必要,否则不要使用AndroidViewModel

查看这个:GOOGLE DOC


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接