为什么推荐使用 ViewModel
架构组件,如果它不处理 process death
?
例如,如果我用 onSaveInstanceState
状况持续 configuration change
和 process death
而 ViewModel
苟延残喘 configuration change
为了生存 process death
要从 ViewModel
并同用 onSaveInstanceState
机制。
我错过了什么?
为什么推荐使用ViewModel架构组件,如果它不处理进程死亡?
我错过了什么?
你是对的,直到2020年1月发生,他们终于发布了。viewmodel-savedstate:1.0.0
然后做了AndroidX活动、碎片和导航最新库版本提供的。SavedStateViewModelFactory
作为默认 ViewModelProvider.Factory
.
现在你可以获得一个 SavedStateHandle
进入你 ViewModel
它可以帮助在整个过程中持久地恢复东西。
class MyViewModel(private val savedStateHandle: SavedStateHandle): ViewModel() {
val someState: MutableLiveData<String> = savedStateHandle.getLiveData("someState")
}
或
class MyAndroidViewModel(application: Application, private val savedStateHandle: SavedStateHandle): AndroidViewModel(application) {
val someState: MutableLiveData<String> = savedStateHandle.getLiveData("someState")
}
而这些将 只管工作 通过它们的默认构造函数作为 SavedStateViewModelFactory
通过反射创建它们。
如果你需要一个 SavedStateHandle
和附加参数,那么就不使用默认的 ViewModelProvider.Factory
,你可以从 AbstractSavedStateViewModelFactory
会给你 SavedStateHandle
进程死亡时自动恢复。
val viewModel = ViewModelProvider(this, myAbstractSavedStateViewModelFactoryImpl).get(MyViewModel::class.java)
或者使用 KTX 的东西
private val viewModel by viewModels { myAbstractSavedStateViewModelFactoryImpl }
你也可以把ViewModels的范围扩大到Jetpack Navigation的NavGraph上,虽然有点麻烦,但还是可以做到的。
inline fun <reified T : ViewModel> SavedStateRegistryOwner.createAbstractSavedStateViewModelFactory(
arguments: Bundle,
crossinline creator: (SavedStateHandle) -> T
): ViewModelProvider.Factory {
return object : AbstractSavedStateViewModelFactory(this, arguments) {
@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel?> create(
key: String, modelClass: Class<T>, handle: SavedStateHandle
): T = creator(handle) as T
}
}
inline fun <reified T : ViewModel> Fragment.navGraphSavedStateViewModels(
@IdRes navGraphId: Int,
crossinline creator: (SavedStateHandle) -> T
): Lazy<T> {
// Wrapped in lazy to not search the NavController each time we want the backStackEntry
val backStackEntry by lazy { findNavController().getBackStackEntry(navGraphId) }
return createViewModelLazy(T::class, storeProducer = {
backStackEntry.viewModelStore
}, factoryProducer = {
backStackEntry.createAbstractSavedStateViewModelFactory(
arguments = backStackEntry.arguments ?: Bundle(), creator = creator
)
})
}
然后...
class MyFragment: Fragment() {
private val mySharedViewModel by navGraphSavedStateViewModels(R.id.registration_graph) { handle ->
MySharedViewModel(handle)
}
}