【问题标题】:ViewModel crashing while trying to recreate without factoryViewModel 在尝试在没有工厂的情况下重新创建时崩溃
【发布时间】:2019-12-03 09:21:00
【问题描述】:

如何在重新创建活动实例后重新创建使用通过Factory 注入的参数创建的ViewModel

ViewModel 有一个这样的构造函数:

class MyViewModel(
        val model: MyModel,
        val repository: MyRepository
) : ViewModel()

我用工厂实例化它:

ViewModelProviders
                    .of(this, MyViewModelFactory(
                            model = MyModel()
                            repository = MyRepository()))
                    .get(MyViewModel::class.java)

我试图像这样恢复ViewModel,而savedInstanceState 不为空(重新创建活动):

ViewModelProviders
                    .of(this)
                    .get(MyViewModel::class.java)

这会导致崩溃,因为 no 0 arguments constructor 存在于 MyViewModel 类中。

如,每次通过工厂: 我的问题是,无论我作为MyModel 传递给ViewModel,并且来自活动Intent,都可能在以后由于用户交互而改变。这意味着,在重新创建时,Intent 中的 MyModel 已过时,已存储在 ViewModel 中并被用户交互篡改。

【问题讨论】:

  • 您的 ViewModel 在活动重新创建期间将被保留(连同它所持有的数据)。 Activity 重新创建后,您不必重新创建它,Android 系统会为您完成。

标签: android android-architecture-components android-viewmodel android-mvvm


【解决方案1】:

这会导致崩溃,因为没有 0 参数构造函数存在 在 MyViewModel 类中。

它会崩溃,因为你没有通过任何工厂来构造ViewModel

如何重新创建使用通过注入的参数创建的 ViewModel 重新创建活动实例后的工厂?

AFAIK,您不必在 savedInstanceState 上手动重新创建 ViewModel。您可以使用viewModel 来存储活动中使用的数据。因此,在重新创建活动时,ViewModelProvider 不会创建viewModel 的新实例,但会为您提供旧实例和保存的数据viewModel中的viewModel不会被清除,所以不用担心savedInstanceState

提示:如果您想管理工厂的创建并改进重新创建过程。你可以查看this article on ViewModel with Dagger

【讨论】:

  • 我认为modelrepository 可能依赖于savedInstanceState 的值而不是视图模型。
  • 我相信,modelrepository 不应该对 Activity 可见,应该通过 viewModel 访问。我们为什么要使用 savedInstanceState ? @ArkaPravaBasu
  • 我相信 DI 的原则恰恰相反。如果 ViewModel 依赖于存储库和模型,则应将它们注入其中,而不是 ViewModel 承担实例化它们的责任。 savedInstanceState 标志的使用是特定于实现和用例的。在不知道Model 存储哪些数据以及Repository 需要哪些数据的情况下,我不确定我会以哪种方式使用它。
【解决方案2】:

MyViewModel 中没有 0 参数构造函数。当您尝试在不提供 Factory 的情况下获取 ViewModel 的实例时,它将查找参数为 0 的构造函数。

无论savedInstanceState 是否为null,您都可以使用它。

ViewModelProviders
                    .of(this, MyViewModelFactory(
                            model,repository))
                    .get(MyViewModel::class.java)

您创建repositorymodel 的方式会根据savedInstanceState 值发生变化,具体取决于您的用例或实现。

【讨论】:

    【解决方案3】:

    可能唯一的答案是,它不能以这种方式完成。如果提供了工厂,则必须始终提供。我不知道ViewModel 娱乐下面的机制,但这些并不像我希望的那样聪明。

    我当前的实现如下所示:

        viewModel = ViewModelProviders
                .of(this, MyFactory(MyRepository()))
                .get(MyMViewModel::class.java)
    
        val binding = DataBindingUtil.setContentView<ActivityCreateFoodstuffBinding>(this, R.layout.my_activity)
        binding.viewModel = viewModel
    
        if (savedInstanceState == null) {
            val model = intent.getParcelableExtra<MyModel>("model")
            viewModel.model.set(model)
        }
    

    我在ViewModel 中使用了一个始终使用存储库的参数构造函数,但是我移走了模型并仅在新创建活动时才设置它。

    【讨论】:

      猜你喜欢
      • 2020-08-20
      • 1970-01-01
      • 2022-10-13
      • 1970-01-01
      • 2016-03-19
      • 1970-01-01
      • 2015-12-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多