1

我使用“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()
     }
    }

其次是将我的视图模型从活动转移到应用程序。在破坏活动后有幸存者。但我不能在应用程序中使用“by viewModels”kotlin 委托。我认为这不是正确的解决方案(但它也有效)。

获取视图模型的正确方法在哪里?

4

1 回答 1

1

问题出在您的ViewModelFactory.getInstance(this)方法上-它将 缓存ViewModelFactory为一个静态实例,该实例可以在活动本身的破坏中幸存下来。除了泄漏活动本身,这意味着第二次创建活动时,ViewModelFactory返回的仍与第一个已销毁的活动相关联。

通过使用by lazy,您已经确保代码在活动的生命周期内只运行一次,因此您应该完全删除instance变量和缓存getInstance

于 2020-11-20T15:31:38.003 回答