IllegalArgumentException 当应用程序启动 post 后退
IllegalArgumentException when app start post backpressed
我使用“by viewModels”kotlin 委托来获取一些视图模型:
val viewModelFactory: ViewModelFactory by lazy { ViewModelFactory.getInstance(this) }
val mainViewModel: MainViewModel by viewModels { viewModelFactory }
视图模型工厂:
class ViewModelFactory private constructor(activity: AppCompatActivity) : AbstractSavedStateViewModelFactory(activity, null) {
private val application = activity.application
// DataSource
private val appDataSource: AppDataSourceImpl by lazy { AppDataSourceImpl(application) }
// Intercator
private val appDataInteractor: AppDataInteractor by lazy {
AppDataInteractor(appDataSource, userDataSource)
}
companion object {
private var instance: ViewModelFactory? = null
fun getInstance(activity: AppCompatActivity): ViewModelFactory {
return instance ?: ViewModelFactory(activity).also {
instance = it
}
}
}
override fun <T : ViewModel> create(
key: String,
modelClass: Class<T>,
handle: SavedStateHandle
): T {
return when {
MainViewModel::class.java.isAssignableFrom(modelClass) -> {
modelClass.getConstructor(AppDataInteractor::class.java, SavedStateHandle::class.java)
.newInstance(appDataInteractor, handle)
}
else -> throw Exception("Unknown ViewModel $modelClass")
}
}
}
当应用程序被反压关闭并再次启动时,它会抛出异常“java.lang.IllegalArgumentException:具有给定密钥的 SavedStateProvider 已注册。”
我看到了两个解决问题的方法。
首先是使用 exitProcess() 而不是 super.onBackPressed()。成功了。
override fun onBackPressed() {
if (drawerLayout.isOpen) drawerLayout.close()
else {
if (navController.currentDestination?.id == R.id.nav_homeFragment) {
exitProcess(1) //super.onBackPressed()
}
else navController.navigateUp()
}
}
其次是将我的视图模型从 activity 转移到应用程序。在破坏activity后还有存活的情况下。但我不能在应用程序中使用“by viewModels”kotlin delegate。我认为这不是正确的解决方案(但它也有效)。
获取视图模型的正确方法在哪里?
问题出在您的 ViewModelFactory.getInstance(this)
方法上 - 它将 ViewModelFactory
缓存为一个静态实例,该实例在 activity 本身被破坏后仍然存在。除了泄漏 activity 本身,这意味着第二次创建 activity 时,返回的 ViewModelFactory
仍然与第一个相关联,已经被销毁 activity。
通过使用 by lazy
,您已经确保代码在 activity 的生命周期内只运行一次,因此您应该删除 instance
变量和其中的缓存getInstance
完全。
我使用“by viewModels”kotlin 委托来获取一些视图模型:
val viewModelFactory: ViewModelFactory by lazy { ViewModelFactory.getInstance(this) }
val mainViewModel: MainViewModel by viewModels { viewModelFactory }
视图模型工厂:
class ViewModelFactory private constructor(activity: AppCompatActivity) : AbstractSavedStateViewModelFactory(activity, null) {
private val application = activity.application
// DataSource
private val appDataSource: AppDataSourceImpl by lazy { AppDataSourceImpl(application) }
// Intercator
private val appDataInteractor: AppDataInteractor by lazy {
AppDataInteractor(appDataSource, userDataSource)
}
companion object {
private var instance: ViewModelFactory? = null
fun getInstance(activity: AppCompatActivity): ViewModelFactory {
return instance ?: ViewModelFactory(activity).also {
instance = it
}
}
}
override fun <T : ViewModel> create(
key: String,
modelClass: Class<T>,
handle: SavedStateHandle
): T {
return when {
MainViewModel::class.java.isAssignableFrom(modelClass) -> {
modelClass.getConstructor(AppDataInteractor::class.java, SavedStateHandle::class.java)
.newInstance(appDataInteractor, handle)
}
else -> throw Exception("Unknown ViewModel $modelClass")
}
}
}
当应用程序被反压关闭并再次启动时,它会抛出异常“java.lang.IllegalArgumentException:具有给定密钥的 SavedStateProvider 已注册。”
我看到了两个解决问题的方法。 首先是使用 exitProcess() 而不是 super.onBackPressed()。成功了。
override fun onBackPressed() {
if (drawerLayout.isOpen) drawerLayout.close()
else {
if (navController.currentDestination?.id == R.id.nav_homeFragment) {
exitProcess(1) //super.onBackPressed()
}
else navController.navigateUp()
}
}
其次是将我的视图模型从 activity 转移到应用程序。在破坏activity后还有存活的情况下。但我不能在应用程序中使用“by viewModels”kotlin delegate。我认为这不是正确的解决方案(但它也有效)。
获取视图模型的正确方法在哪里?
问题出在您的 ViewModelFactory.getInstance(this)
方法上 - 它将 ViewModelFactory
缓存为一个静态实例,该实例在 activity 本身被破坏后仍然存在。除了泄漏 activity 本身,这意味着第二次创建 activity 时,返回的 ViewModelFactory
仍然与第一个相关联,已经被销毁 activity。
通过使用 by lazy
,您已经确保代码在 activity 的生命周期内只运行一次,因此您应该删除 instance
变量和其中的缓存getInstance
完全。