[英]Ways of making async service calls in Android? and when to use which?
[英]Android different ways to create viewModel object which one to use when?
我最近开始使用 ViewModel 和 AndroidViewModel,我看到初始化 viewModel 实例有不同的方法,对我来说一切正常,我只想知道什么时候使用哪个? 我应该在哪里初始化viewModel object? 以下都是获取 viewModel 实例并为我工作的不同方法:
val myViewModel1 = ViewModelProvider(this, ViewModelProvider.NewInstanceFactory()).get(MyViewModel::class.java)
val myViewModel2 = ViewModelProvider.AndroidViewModelFactory(this.application).create(MyViewModel::class.java)
val myViewModel3 = ViewModelProvider(this).get(MyViewModel::class.java)
val myViewModel4: MyViewModel by viewModels()
val myViewModel5 by viewModels<MyViewModel>()
对我来说最简单和最简单的是第 3、第 4 和第 5 种方法,但是我不知道所有五种方法有什么区别,也请告诉我是否有任何其他方法或最佳方法来初始化我的 viewModel object,我在声明全局变量时对其进行初始化,是否可以在声明时进行初始化,或者应该在某个生命周期方法中完成?
3是获取(并在必要时创建)没有构造函数参数的 ViewModel 的标准方法。 在内部,这是1传递一个调用空构造函数( NewInstanceFactory()
)的工厂。
AndroidViewModel
是ViewModel
的子类,它会自动传入application
引用,以防您需要访问应用程序上下文等内容。 所以即使你的 AndroidViewModel 没有参数,创建它的工厂也需要传入一个application
,这就是2正在做的事情。
默认情况下,这一切都使用3为您处理 - 如果您的 VM 需要配置一些额外的参数,您只需要定义和使用工厂。
4和5是一回事,只是在不同的地方指定了类型(你只需要一个声明,另一个将被推断)。 它们是来自 KTX 库的代表,它们与3执行相同的操作,但它们在 IMO 中更具可读性 - 特别是如果您正在混合范围,例如使用by viewModels
来获取 Fragment 自己的 VM,也可以by activityViewModels
让活动的虚拟机与该片段和其他片段共享数据。
它们也是lazy
委托(据我所知),这意味着 VM 仅在首次访问时才被实例化。 这通常会在生命周期的后期发生(而不是在 object 首次构建时)。 我不确定在构造时初始化 VM是否有问题,但我见过的所有官方示例似乎都在onCreate
(或附近)中获取它
如果有人在寻找深入的答案,请检查这个,这里我们有以下方法来创建或获取 viewModel object:
val myViewModel1 = ViewModelProvider(this, ViewModelProvider.NewInstanceFactory()).get(MyViewModel::class.java)
myViewModel2 = ViewModelProvider.AndroidViewModelFactory(this.application).create(MyViewModel::class.java)
val myViewModel3 = ViewModelProvider(this).get(MyViewModel::class.java)
val myViewModel4: MyViewModel by viewModels()
val myViewModel5 by viewModels<MyViewModel>()
所有人都做同样的事情,唯一的两个关键区别是:
让我们看看lazy loading and without lazy loading
,前三个没有委托by
这意味着 object 没有延迟加载,因此开发人员有责任仅在创建活动或片段时创建视图模型 object附加到活动,这意味着前三种方法(1、2、3)不能在全局 scope 中使用,如果在全局 scope 中使用,则该变量必须是带有lateint
或 Z37A6259CC0C1DAE29BD19A78668 初始化的 var , 2, 3) 必须发生在 onCreate 或 onViewCreated 中(在片段的情况下)。
因此,创建 viewModel object 的最佳方法是使用 (4, 5) 的by
,两者相同,但语法略有不同,我选择 4 是因为它简单易读。
val myViewModel4: MyViewModel by viewModels()
by
委托提供了延迟加载实例的灵活性,您可以在全局 scope 定义 viewModel 并摆脱样板代码,如果您尝试在没有委托的情况下在全局 scope 初始化 viewModel,则应用程序将崩溃,因为 viewModel 将尝试在创建活动之前进行初始化(它不会延迟加载 viewModel 实例)。
现在让我们看看如何使用多个参数进行延迟加载,问题中没有提到6th
方法。
如果您的视图 model 中有多个参数并且不使用任何依赖注入,则可以使用 ViewModelFactory 实现,然后延迟加载它:
val myViewModelWithParm: MyViewModel by viewModels { MyViewModelFactory(application, "param1", "param2") }
ViewModelFactory 实现:
class MyViewModelFactory(val application: Application, val param1: String, val param2: String) :
ViewModelProvider.Factory {
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
return MyViewModel(application, param1, param2) as T
}
}
到目前为止,我们已经清楚了委托初始化 (4, 5),以及它与 (1, 2, 3) 的不同之处现在让我们看看前 3 种方法 (1, 2, 3) 的区别。
让我们首先检查 1 和 2。
val myViewModel1 = ViewModelProvider(this, ViewModelProvider.NewInstanceFactory()).get(MyViewModel::class.java)
myViewModel2 = ViewModelProvider.AndroidViewModelFactory(this.application).create(MyViewModel::class.java)
它们之间的主要区别是一个使用ViewModelProvider.NewInstanceFactory
而另一个使用ViewModelProvider.AndroidViewModelFactory
,所以我检查了这两个类的源代码,发现ViewModelProvider.AndroidViewModelFactory
实际上是ViewModelProvider.NewInstanceFactory
的实现,它覆盖了create
function 这意味着两者正在做同样的事情,如果我们想要多个参数,最好选择这两种方法但是我们必须重写ViewModelProvider.NewInstanceFactory
来创建我们自己的工厂,就像在这里完成的那样
现在是第三个:
val myViewModel3 = ViewModelProvider(this).get(MyViewModel::class.java)
当我们的 ViewModel 中没有多个参数并且不想延迟加载 object 时,这是 1 和 2 的简单形式。
注意:我强烈推荐方法 4 或 5(两者语法不同),因为这是最适合和最佳编写的方法,如果您没有多个 arguments,如果您有多个 arguments,您可以使用该方法6 通过实现ViewModelProvider.Factory
在答案中提到。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.