android - 通过 View 模型和使用工厂创建 View 模型之间的区别?

标签 android kotlin android-viewmodel android-mvvm

我在学习ViewModel将其应用于 MVVM设计模式。
有一种方法使用 by viemodels()以及使用 ViewModelProvider.Factory 的方法在 View 模型创建中。by viewModels()创建一个 ViewModel object .ViewModelProvider.Factory还创建 Viewmodel objects .
这两者有什么区别?
另外,在一些示例代码中,我看到了注释中的代码 3 , 它使用 by viewModels()factory一起。这是什么意思?

class WritingRoutineFragment : Fragment() {
    private val viewModel: WriteRoutineViewModel by viewModels() // 1
    private lateinit var viewModelFactory: WriteRoutineViewModelFactory

//  private val viewModel: WriteRoutineViewModel by viewModels(
//        factoryProducer = { viewModelFactory } // 3.What does this code mean?
//  )

    override fun onCreateView(inflater: LayoutInflater,
                              container: ViewGroup?,
                              savedInstanceState: Bundle?): View? {
        _binding = FragmentWritingRoutineBinding.inflate(inflater, container, false)
        viewModelFactory = WriteRoutineViewModelFactory()
//        viewModel = ViewModelProvider(this, viewModelFactory).get(WriteRoutineViewModel::class.java) // 2
        return binding.root
    }

最佳答案

如果您的 ViewModel 有一个零参数构造函数,或者如果它有一个构造函数,其中唯一的参数是 Application 类型并且它是 AndroidViewModel 的子类,那么您不需要工厂。 (或者,如果您的构造函数是上述任一加上 SavedStateHandle。) View 模型工厂是一个能够实例化具有更复杂构造函数的 ViewModel 的类。
在不使用委托(delegate)的情况下实例化 ViewModel 时,您必须使用 lateinit var对于属性,因为直到 onCreateView 才能实例化它.
如果您的 ViewModel 不需要工厂,那么在没有委托(delegate)的情况下执行此操作的过程将如下所示:

class WritingRoutineFragment : Fragment() {
    private lateinit var viewModel: WriteRoutineViewModel

    override fun onCreateView(inflater: LayoutInflater,
                              container: ViewGroup?,
                              savedInstanceState: Bundle?): View? {
        //...
        viewModel = ViewModelProvider(this, viewModelFactory).get(WriteRoutineViewModel::class.java)
        //...
    }
}
如果它确实需要一个工厂,它看起来像这样,您必须在其中实例化一个工厂并将其传递给 ViewModelProvider 构造函数:
class WritingRoutineFragment : Fragment() {
    private lateinit var viewModel: WriteRoutineViewModel

    override fun onCreateView(inflater: LayoutInflater,
                              container: ViewGroup?,
                              savedInstanceState: Bundle?): View? {
        //...
        viewModel = ViewModelProvider(this, WriteRoutineViewModelFactory()).get(WriteRoutineViewModel::class.java)
        //...
    }
}
委托(delegate)允许您在 val 中更简洁地执行此操作。就在声明站点,因此您不必在 onCreateView 中对 View 模型属性进行任何设置.第一次使用该属性时,它将延迟创建 ViewModel。优点是代码更简洁明了(lateinit var 将属性与其声明分开并使其可变,即使它永远不会改变)。
因此,不需要工厂时的上述代码如下所示:
class WritingRoutineFragment : Fragment() {
    private val viewModel: WriteRoutineViewModel by viewModels()
}
如果你确实需要一个工厂,它看起来像这样。你传递给它一个实例化工厂的函数,这很容易用 lambda 完成:
class WritingRoutineFragment : Fragment() {
    private val viewModel: WriteRoutineViewModel by viewModels { WriteRoutineViewModelFactory() }
}
您的示例中的代码有一个额外的属性来保存工厂,这是一个不必要的复杂性,因为您永远不需要直接访问它。你的例子中的工厂有一个空的构造函数也很奇怪,因为如果工厂没有任何状态,那么它就没有数据可以传递给 ViewModel 构造函数。

关于android - 通过 View 模型和使用工厂创建 View 模型之间的区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67810019/

相关文章:

java - 使用 ndk 从位图计算像素

android - MuPDF Android Pdf 适合屏幕

kotlin - 如何将分机转为成员(member)?

android - 从Android Kotlin中的数据库获取值为真的行数

android - 如何在 Kotlin 中初始化未知类型的属性?

android - 未找到 DefaultActivityViewModelFactory

java - AndEngine:如何删除启动默认 Activity 屏幕

java - 单例还是静态类?

android - 将 ViewModel 绑定(bind)到服务是否正确?

java - ViewModel 问题显示 MV VM 架构中的数据库更改