已注册具有给定键的 SavedStateProvider [英] SavedStateProvider with the given key is already registered
问题描述
我目前正在尝试使用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屋!