已注册具有给定键的 SavedStateProvider [英] SavedStateProvider with the given key is already registered

查看:116
本文介绍了已注册具有给定键的 SavedStateProvider的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在尝试使用savedState 的新Jetpack ViewModel.

I'm currently trying the new Jetpack ViewModel with savedState.

    implementation 'androidx.lifecycle:lifecycle-viewmodel-savedstate:1.0.0-rc01'

我正在使用 1 个活动并尝试与 2 个片段共享 1 个 ViewModel,但是当我尝试启动第二个片段时,我从标题中收到错误消息.

I'm using 1 Activity and trying to share 1 ViewModel with 2 Fragments but when I try to start the second fragment I get the error from the title.

这就是我使用savedInstance调用ViewModel的方式:

This is how I'm calling the ViewModel with the savedInstance:

    val repository = (activity?.application as App).getRepository()
    viewModel = activity?.run {
        ViewModelFactory(repository, this, savedInstanceState).create(MainViewModel::class.java)
    } ?: throw Exception("Invalid Activity")

这是我的日志:

java.lang.IllegalArgumentException: SavedStateProvider with the given key is already registered
    at androidx.savedstate.SavedStateRegistry.registerSavedStateProvider(SavedStateRegistry.java:111)
    at androidx.lifecycle.SavedStateHandleController.attachToLifecycle(SavedStateHandleController.java:50)
    at androidx.lifecycle.SavedStateHandleController.create(SavedStateHandleController.java:70)
    at androidx.lifecycle.AbstractSavedStateViewModelFactory.create(AbstractSavedStateViewModelFactory.java:67)
    at androidx.lifecycle.AbstractSavedStateViewModelFactory.create(AbstractSavedStateViewModelFactory.java:84)
    at com.xxx.yyy.presentation.details.DetailsFragment.onCreate(DetailsFragment.kt:29)
    at androidx.fragment.app.Fragment.performCreate(Fragment.java:2586)
    at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManagerImpl.java:838)
    at androidx.fragment.app.FragmentTransition.addToFirstInLastOut(FragmentTransition.java:1197)
    at androidx.fragment.app.FragmentTransition.calculateFragments(FragmentTransition.java:1080)
    at androidx.fragment.app.FragmentTransition.startTransitions(FragmentTransition.java:119)
    at androidx.fragment.app.FragmentManagerImpl.executeOpsTogether(FragmentManagerImpl.java:1866)
    at androidx.fragment.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManagerImpl.java:1824)
    at androidx.fragment.app.FragmentManagerImpl.execPendingActions(FragmentManagerImpl.java:1727)
    at androidx.fragment.app.FragmentManagerImpl$2.run(FragmentManagerImpl.java:150)

看起来它正在尝试使用已经注册的 SavedState 并因此出现错误?我认为这就是图书馆的全部意义所在.任何人都可以帮助或指出如何使用此传递参数到 ViewModel 和使用 savedStateHandle 吗?

Looks like it's trying to use a SavedState which was already registered and hence the error? I thought that was the whole point of the library. Can anyone help or point on how to use this passing arguments to the ViewModel and using the savedStateHandle?

推荐答案

你永远不应该自己调用 create - 这样做,你实际上并没有使用保留的 ViewModel 已创建,导致 AbstractSavedStateViewModelFactory 尝试多次注册相同的密钥.

You should never be calling create yourself - by doing so, you're not actually using the retained ViewModel that is already created, causing the AbstractSavedStateViewModelFactory to attempt to register the same key more than once.

相反,您应该将 ViewModelFactory 传递给 ViewModelProvider 实例以检索已经存在的 ViewModel 或仅在必要时创建它:

Instead, you should be passing your ViewModelFactory to a ViewModelProvider instance to retrieve the already existing ViewModel or creating it only if necessary:

val repository = (activity?.application as App).getRepository()
viewModel = activity?.run {
    val factory = ViewModelFactory(repository, this, savedInstanceState)
    ViewModelProvider(this, factory).get(MainViewModel::class.java)
} ?: throw Exception("Invalid Activity")

如果您依赖 1.1.0 或更高版本的 fragment-ktx,则可以改用 by activityViewModels Kotlin 属性委托,懒惰地使用 ViewModelProvider 引擎盖下:

If you depend on fragment-ktx of version 1.1.0 or higher, you can instead use the by activityViewModels Kotlin property delegate, which lazily uses ViewModelProvider under the hood:

val viewModel: MainViewModel by activityViewModels {
    val repository = (activity?.application as App).getRepository()
    ViewModelFactory(repository, requireActivity(), savedInstanceState)
}

这篇关于已注册具有给定键的 SavedStateProvider的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆