【问题标题】:Type cast / make genric viewModel to be passed as parameter类型转换/使通用视图模型作为参数传递
【发布时间】:2021-06-17 18:19:04
【问题描述】:

我正在处理一个自定义对话框片段,该片段正在从具有不同viewModels 的两个不同视图中使用/调用。而不是在Dialog类的构造函数参数中传递两个单独的viewModels

class CustomeDialog(var viewModel1: ViewModelA ?= null, var viewModel2 : ViewModelB ?= null) : DialogFragment()

我需要询问/找出一种方法,我可以将 类型的参数设置为对话框,这样我就可以输入任何 viewModel 的种姓,我想要。

类似的,

class CustomDialog<T:ViewModel> : DialogFragment()

在代码中,它会是这样的

val mdialog1: CustomeDialog by lazy { CustomeDialog(viewModel as ViewModelA) }

还有

 val mdialog2: CustomeDialog by lazy { CustomeDialog(viewMode2 as ViewModelB) }

【问题讨论】:

  • 您不应该将片段引用存储在惰性属性中。如果配置发生更改,则 OS 将重新创建 Fragment,当您的属性再次被访问时,它将创建该 Fragment 的其他实例,因此您将获得对 not 在屏幕上。如果您需要访问现有的 Fragment,请通过 Fragment Manager 找到它。

标签: android kotlin generics android-viewmodel android-mvvm


【解决方案1】:

您可以在接受泛型ViewModel 参数的泛型类中创建辅助构造函数:

class CustomeDialog<T : ViewModel>() : DialogFragment() {
    constructor(viewmodel: T) : this()
}

而且用法和你做的一样:

lateinit var viewModel: ViewModel
val mdialog1: CustomeDialog<ViewModelA> by lazy { CustomeDialog(viewModel as ViewModelA) }
lateinit var viewModel2: ViewModelA
val mdialog2: CustomeDialog<ViewModelA> by lazy { CustomeDialog(viewModel2) }

更新:

如何根据类型在对话框中初始化 viewModel。例如。如果 VM1 在构造函数中传递,则 var dialogViewModel = WHAT??,

要求有一个带有通用ViewModel 的对话框,因此它的类型是通用的,因为在实例化之前它是未知的。

是的,我需要一个通用的本地 var dialogViewModel,正如我所提到的,整个逻辑都依赖于这个 dvm

可以在二级构造函数中初始化:

class CustomDialog<T : ViewModel>() : DialogFragment() {

    lateinit var dialogViewModel: T

    constructor(viewmodel: T) : this() {
        dialogViewModel = viewmodel
    }
}

【讨论】:

  • 好的,那么现在,如何根据类型在对话框中初始化 viewModel。例如。如果VM1传入构造函数,那么var dialogViewModel = WHAT??,因为整个逻辑都是基于dialogViewModel
  • @ZainabZafar GlCodeSearchDialog 不是有一个通用的ViewModel 类型,那为什么需要根据某个类型类型来初始化呢? .. 或者你想要一个通用的本地dialogViewModel var?这在 OP 上并不清楚
  • 是的,我需要一个通用的本地 var dialogViewModel,正如我所提到的,整个逻辑都依赖于这个 dvm,所以我只需要根据我在构造函数中传递的 viewModel 类型来初始化它,所以我的整个逻辑保持不变,只有 dialogViewModel 获得正在传递的所需 viewModel 的引用
  • @ZainabZafar 请查看更新后的答案
  • 这不起作用,因为操作系统在配置更改后重新创建片段时不会使用辅助构造函数。
【解决方案2】:

这种策略行不通。操作系统使用反射及其空构造函数重新创建您的 Fragment。它可以使用 Bundle 值将状态恢复到替换 Fragment,但类类型不是 Bundle 的有效数据类型。

我能想到的最接近的方法是将其设为抽象类,然后创建具有具体类型的简单子类。

abstract class CustomDialog<T: ViewModel>(viewModelType: KClass<out T>): DialogFragment() {
    val viewModel: T by createViewModelLazy(viewModelType, { viewModelStore })
}

class CustomDialogA: CustomDialog<ViewModelA>(ViewModelA::class)
class CustomDialogB: CustomDialog<ViewModelB>(ViewModelB::class)

【讨论】:

    猜你喜欢
    • 2018-05-04
    • 1970-01-01
    • 2013-04-18
    • 1970-01-01
    • 2019-04-24
    • 2014-06-06
    • 2021-02-12
    • 2019-02-27
    相关资源
    最近更新 更多