虽然是同样的异常,但是我的情况和SavedStateProvider with the given key is already registered不一样因为我正在使用 Nav-graph Scoped ViewModels,
将 AbstractSavedStateViewModelFactory
与 navGraphViewModels 一起使用时发生异常。
从startFragment,转到FirstPageFragment,navigateUp()
回到startFragment,然后再次访问FirstPageFragment ->crash
class FirstPageFragment: Fragment() {
private val myViewModel: MyViewModel by navGraphViewModels(R.id.nav_mission){
MyViewModel.Factory(requireActivity(), "hello world1")
}
...
我的工厂
class MyViewModel(application: Application,
savedStateHandle: SavedStateHandle,
val someString: String) : AndroidViewModel(application){
class Factory(val activity: Activity, val someString: String):
AbstractSavedStateViewModelFactory(activity as SavedStateRegistryOwner, null) {
override fun <T : ViewModel?> create(
key: String,
modelClass: Class<T>,
handle: SavedStateHandle
): T {
if (modelClass.isAssignableFrom(MyViewModel::class.java)) {
@Suppress("UNCHECKED_CAST")
return MyViewModel(activity.application, handle, someString) as T
}
throw IllegalArgumentException("Unable to construct viewmodel")
}
}
...
}
这是我的 navGraph,ViewModel 用于 firstPageFragment 和 SecondPageFragment
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/nav_main_activity"
app:startDestination="@id/startFragment">
<fragment
android:id="@+id/startFragment"
android:name="com.example.savestatehandledemo.StartFragment"
android:label="FirstPageFragment" >
<action
android:id="@+id/action_startFragment_to_nav_mission"
app:destination="@id/nav_mission" />
</fragment>
<navigation android:id="@+id/nav_mission"
app:startDestination="@id/firstPageFragment">
<fragment
android:id="@+id/firstPageFragment"
android:name="com.example.savestatehandledemo.FirstPageFragment"
android:label="FirstPageFragment" >
</fragment>
<fragment
android:id="@+id/secondPageFragment"
android:name="com.example.savestatehandledemo.SecondPageFragment"
android:label="SecondPageFragment" >
</fragment>
</navigation>
</navigation>
我创建了一个最小示例来重现该问题。 https://github.com/yatw/saveStateHandleDemo/tree/master/app/src/main/java/com/example/savestatehandledemo
此异常仅在进入导航图时发生。
请帮忙!
最佳答案
所以我找到了这个异常的原因,我将 Activity 作为 AbstractSavedStateViewModelFactory
中的 SavedStateRegistryOwner 传递。
第二次访问 navGraph 时,我传递了相同的 Activity 和内部类 SavedStateHandleController
,SavedStateRegistry
不知何故已经保存了状态。
(请写这部分的人解释并写入文档)
所以传入navGraph getBackStackEntry
更新的 viewModel 工厂
class MyViewModel(application: Application,
savedStateHandle: SavedStateHandle,
val someString: String) : AndroidViewModel(application){
class Factory(val application: Application,
val savedStateRegistryOwner: SavedStateRegistryOwner,
val someString: String):
AbstractSavedStateViewModelFactory(
savedStateRegistryOwner,
null) {
override fun <T : ViewModel?> create(
key: String,
modelClass: Class<T>,
handle: SavedStateHandle
): T {
if (modelClass.isAssignableFrom(MyViewModel::class.java)) {
@Suppress("UNCHECKED_CAST")
return MyViewModel(application, handle, someString) as T
}
throw IllegalArgumentException("Unable to construct viewmodel")
}
}
在 fragment 中使用它
class FirstPageFragment: Fragment() {
private val myViewModel: MyViewModel by navGraphViewModels(R.id.nav_mission){
MyViewModel.Factory(requireActivity().application,
findNavController().getBackStackEntry(R.id.nav_mission),
"hello world1")
}
特别感谢 EpicPandaForce,https://stackoverflow.com/a/61649394/5777189
关于android - 抽象保存状态 View 模型工厂 : SavedStateProvider with the given key is already registered,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69777585/