通过视图模型和使用工厂创建视图模型之间的区别?
Difference between by viewmodels and viewmodel creation using Factory?
我正在研究 ViewModel
以将其应用于 MVVM
设计模式。
在视图模型创建中有一个使用 by viemodels()
的方法和一个使用 ViewModelProvider.Factory
的方法。
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 的子class,那么您不需要工厂。 (或者,如果您的构造函数是上述任何一个加上 SavedStateHandle。)视图模型工厂是一个 class,它能够实例化具有更复杂构造函数的 ViewModel。
在不使用委托的情况下实例化 ViewModel 时,您必须为 属性 使用 lateinit var
,因为在 onCreateView
.
之前无法实例化它
如果您的 ViewModel 不需要工厂,那么在没有委托的情况下执行它的过程如下所示:
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)
//...
}
}
委托允许您在声明站点的 val
中更简洁地执行此操作,因此您不必在 onCreateView
中对视图模型 属性 进行任何设置].它会在第一次使用 属性 时延迟创建 ViewModel。优点是代码更简洁明了(lateinit var
将 属性 从它的声明中分离出来并使其可变,即使它永远不会改变)。
所以上面的代码在不需要工厂时看起来像:
class WritingRoutineFragment : Fragment() {
private val viewModel: WriteRoutineViewModel by viewModels()
}
如果你确实需要一个工厂,它看起来像这样。你传递给它一个实例化工厂的函数,这很容易用 lambda 完成:
class WritingRoutineFragment : Fragment() {
private val viewModel: WriteRoutineViewModel by viewModels { WriteRoutineViewModelFactory() }
}
您的示例中的代码有一个额外的 属性 只是为了保存工厂,这是不必要的复杂化,因为您永远不需要直接访问它。您示例中的工厂有一个空构造函数也很奇怪,因为如果工厂没有任何状态,那么它就没有数据要传递给 ViewModel 构造函数。
我正在研究 ViewModel
以将其应用于 MVVM
设计模式。
在视图模型创建中有一个使用 by viemodels()
的方法和一个使用 ViewModelProvider.Factory
的方法。
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 的子class,那么您不需要工厂。 (或者,如果您的构造函数是上述任何一个加上 SavedStateHandle。)视图模型工厂是一个 class,它能够实例化具有更复杂构造函数的 ViewModel。
在不使用委托的情况下实例化 ViewModel 时,您必须为 属性 使用 lateinit var
,因为在 onCreateView
.
如果您的 ViewModel 不需要工厂,那么在没有委托的情况下执行它的过程如下所示:
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)
//...
}
}
委托允许您在声明站点的 val
中更简洁地执行此操作,因此您不必在 onCreateView
中对视图模型 属性 进行任何设置].它会在第一次使用 属性 时延迟创建 ViewModel。优点是代码更简洁明了(lateinit var
将 属性 从它的声明中分离出来并使其可变,即使它永远不会改变)。
所以上面的代码在不需要工厂时看起来像:
class WritingRoutineFragment : Fragment() {
private val viewModel: WriteRoutineViewModel by viewModels()
}
如果你确实需要一个工厂,它看起来像这样。你传递给它一个实例化工厂的函数,这很容易用 lambda 完成:
class WritingRoutineFragment : Fragment() {
private val viewModel: WriteRoutineViewModel by viewModels { WriteRoutineViewModelFactory() }
}
您的示例中的代码有一个额外的 属性 只是为了保存工厂,这是不必要的复杂化,因为您永远不需要直接访问它。您示例中的工厂有一个空构造函数也很奇怪,因为如果工厂没有任何状态,那么它就没有数据要传递给 ViewModel 构造函数。