简体   繁体   English

在 android 中使用“by viewModels()”与“ViewModelProvider(this).get(ViewModel::class.java)”查看 model 初始化

[英]View model initialization using “by viewModels()” vs “ViewModelProvider(this).get(ViewModel::class.java)” in android

We can initialize the ViewModel class using我们可以使用初始化ViewModel class

private val viewModel: CharactersViewModel by viewModels()

or或者

viewModel = ViewModelProvider(this).get(CharactersViewModel::class.java)

Herer CharactersViewModel is our ViewModel class. Herer CharactersViewModel 是我们的 ViewModel class。 My question is when to use which?我的问题是什么时候使用哪个? Do both contain the same purpose?两者是否包含相同的目的? I have read the android official documentation of ViewModel.The documentation says by viewModels() Kotlin property delegate .我已阅读 ViewModel 的 android 官方文档。该文档by viewModels() Kotlin property delegate说。 But unfortunately failed to understand it.但遗憾的是没能看懂。 Can anyone help me understand this?谁能帮我理解这一点?

Both of them do the same thing, but there is a discriminative advantage for the first one.两者都做同样的事情,但对第一个有区分优势。 Kotlin property delegation uses the idea of Lazy Initialization . Kotlin 属性委托使用了Lazy Initialization的思想。 On Wikipedia you can find a brief definition for it:Wikipedia上,您可以找到它的简要定义:

In computer programming, lazy initialization is the tactic of delaying the creation of an object, the calculation of a value, or some other expensive process until the first time it is needed.在计算机编程中,延迟初始化是延迟 object 的创建、值的计算或其他一些昂贵的过程,直到第一次需要它的策略。 It is a kind of lazy evaluation that refers specifically to the instantiation of objects or other resources.它是一种惰性求值,专门指对象或其他资源的实例化。

Therefore, when you use the first approach you mentioned, you take the advantage of lazy properties.因此,当您使用您提到的第一种方法时,您利用了惰性属性。 It means that the ViewModel instance becomes created only upon first access.这意味着 ViewModel 实例仅在首次访问时创建。

Given below code as an example:以下面的代码为例:

class YourFragment : Fragment() {

    private val viewModel: CharactersViewModel by viewModels()

    // other codes ...

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        
        // doing some view initialization ...

        viewModel.someLiveData.observe(viewLifecycleOwner) {
            // ...
        }
    }
}

If viewModel.someLiveData.observe(viewLifecycleOwner) is the first time that the viewModel field is touched, the instantiation of it will happen there.如果viewModel.someLiveData.observe(viewLifecycleOwner)是第一次触摸viewModel字段,它将在那里发生实例化。 (creation of a CharactersViewModel instance) (创建CharactersViewModel实例)

So, using lazy initialization of objects like the view model reduces the start-up impact of your fragment which leads to faster loading and showing its content as opposed to direct initialization of them.因此,使用像视图 model 这样的对象的延迟初始化可以减少片段的启动影响,从而加快加载和显示其内容,而不是直接初始化它们。

Those two statements are equal.这两个陈述是相等的。

The Kotlin keyword by simply saves you some code, saves you the pain of using reflection to access your VM and looks way cleaner, if you as me. Kotlin 关键字只是by您节省了一些代码,为您节省了使用反射访问 VM 的痛苦,并且看起来更干净,如果您像我一样。

Either or should do the job for ya:)要么或应该为你做这项工作:)

To add to the already mentioned answers,要添加到已经提到的答案,

The lateinit modifier tells the type-checker that a var property will be initialised "by magic" before it is used, and so does not need to be given a nullable type. lateinit 修饰符告诉类型检查器 var 属性将在使用之前“通过魔法”初始化,因此不需要赋予可为空的类型。 It prevents the type checker helping you initialise properties correctly.它会阻止类型检查器帮助您正确初始化属性。 Instead, programming errors in initialisation are reported by exceptions later at runtime.相反,初始化中的编程错误会在运行时稍后由异常报告。

It is intended for when Kotlin code is interfacing with legacy Java frameworks that use reflection to poke values into fields behind the back of the type checker and visibility modifiers.它适用于 Kotlin 代码与传统 Java 框架接口时使用反射将值插入类型检查器和可见性修饰符后面的字段中。

We should try to avoid lateinit in our code, if possible, in this case you should use如果可能的话,我们应该尽量避免在我们的代码中使用lateinit ,在这种情况下你应该使用

private val viewModel: CharactersViewModel by viewModels()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 ViewModelProviders.of(FragmentActivity).get(ViewModel :: class.java)要求活动而不是get()调用中的viewmodel - ViewModelProviders.of(FragmentActivity).get(ViewModel::class.java) asking for activity instead of viewmodel in get() call Android Studio - ActivityClass::class.java - Android Studio - ActivityClass::class.java 在 VIew 中如何使用 ViewModel 和 ViewModelProvider - In VIew how to use ViewModel with ViewModelProvider 如何使用 ViewModelProvider 创建我的 ViewModel 类的实例 - How to create Instance of my ViewModel Class using ViewModelProvider 使用模拟 ViewModel 测试 Android ViewModelProvider - Testing Android ViewModelProvider with a mock ViewModel ViewModelProvider.of 和 ViewModelProvider 在 Android Java 中均已弃用 - ViewModelProvider.of and ViewModelProvider both are deprecated in Android Java hiltView模型<viewmodel> () 对比 viewModels()</viewmodel> - hiltViewModel<ViewModel>() vs by viewModels() 什么意思::class.java - What is the meaning of ::class.java 何时在 Android 中使用多个 ViewModel 与共享 ViewModel? - When to use multiple ViewModels vs shared ViewModel in Android? 使用 ViewModelProvider(this) 初始化 ViewModel 实例时出现问题 - Problem initializing ViewModel instance using ViewModelProvider(this)
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM