MVVM:根据用例使用不同的 ViewModel 实现
MVVM: Use different ViewModel Implementation depending on Use-case
我有一个片段应该在多个用例中重复使用,例如名为 AddOrEditRecipeFragment
,此片段可用于创建或编辑食谱,因为无论您创建或编辑食谱,它都是相同的 UI。
但我想使用 AddReceipeViewModel
或 EditRecipeViewModel
实例,具体取决于用例,它由 Fragment 上的 FragmentArgument 标识。 AddReceipeViewModel
和EditRecipeViewModel
都实现了相同的接口,所以我目前做的是:
private val viewModel: MyViewModelInterface by lazy {
val mode = // ... just get a flag from the arguments which indicates which mode we are in
val vm: MyViewModelInterface = when(mode) {
Mode.EDIT -> { val vm: EditRecipeViewModel by activityViewModel(); vm }
Mode.ADD -> { val vm: AddRecipeViewModel by activityViewModel(); vm }
vm
}
这感觉很不对,因为知道的片段需要知道 MyViewModelInterface
的所有可能实现。有人知道更好的解决方案吗?
谢谢
您可以创建一个 factory
并将模式传递给工厂,将决定实例化哪个视图模型的逻辑留给 factory
因此片段仅取决于接口。
在你的片段中添加这个
private val factory = ViewModelFactory() // inject it instead if using DI
private val viewModel: MyVieModelInterface by activityViewModels {
factory
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val mode = // get mode from arguments
factory.mode = mode
}
与
abstract class MyVieModelInterface : ViewModel() /* rename as it's not an interface */ {
}
class ViewModelFactory : ViewModelProvider.Factory {
lateinit var mode: Mode
@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel> create(modelClass: Class<T>): T = if (modelClass.isAssignableFrom(MyVieModelInterface::class.java)) {
when (mode) {
Mode.EDIT -> EditViewModel(/* stuff here */)
Mode.ADD -> AddViewModel(/* stuff here */)
}
} else {
throw IllegalArgumentException("Unknown ViewModel class [$modelClass]")
}
}
我有一个片段应该在多个用例中重复使用,例如名为 AddOrEditRecipeFragment
,此片段可用于创建或编辑食谱,因为无论您创建或编辑食谱,它都是相同的 UI。
但我想使用 AddReceipeViewModel
或 EditRecipeViewModel
实例,具体取决于用例,它由 Fragment 上的 FragmentArgument 标识。 AddReceipeViewModel
和EditRecipeViewModel
都实现了相同的接口,所以我目前做的是:
private val viewModel: MyViewModelInterface by lazy {
val mode = // ... just get a flag from the arguments which indicates which mode we are in
val vm: MyViewModelInterface = when(mode) {
Mode.EDIT -> { val vm: EditRecipeViewModel by activityViewModel(); vm }
Mode.ADD -> { val vm: AddRecipeViewModel by activityViewModel(); vm }
vm
}
这感觉很不对,因为知道的片段需要知道 MyViewModelInterface
的所有可能实现。有人知道更好的解决方案吗?
谢谢
您可以创建一个 factory
并将模式传递给工厂,将决定实例化哪个视图模型的逻辑留给 factory
因此片段仅取决于接口。
在你的片段中添加这个
private val factory = ViewModelFactory() // inject it instead if using DI
private val viewModel: MyVieModelInterface by activityViewModels {
factory
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val mode = // get mode from arguments
factory.mode = mode
}
与
abstract class MyVieModelInterface : ViewModel() /* rename as it's not an interface */ {
}
class ViewModelFactory : ViewModelProvider.Factory {
lateinit var mode: Mode
@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel> create(modelClass: Class<T>): T = if (modelClass.isAssignableFrom(MyVieModelInterface::class.java)) {
when (mode) {
Mode.EDIT -> EditViewModel(/* stuff here */)
Mode.ADD -> AddViewModel(/* stuff here */)
}
} else {
throw IllegalArgumentException("Unknown ViewModel class [$modelClass]")
}
}