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完全。