ViewModel 和进程死亡

Pav*_*ley 1 android android-viewmodel

ViewModel如果不处理,为什么建议使用架构组件process death

例如,如果我保存状态,onSaveInstanceState状态为configuration change和都持续存在process death,而ViewModel只生存configuration change,生存process death需要从中获取状态ViewModel并使用相同的onSaveInstanceState机制。

我想念什么?

Epi*_*rce 5

如果不处理进程死亡,为什么推荐使用 ViewModel 架构组件?

我想念什么?

你是对的,直到 2020 年 1 月发生了,当他们终于发布viewmodel-savedstate:1.0.0,然后将 AndroidX Activity、Fragment 和 Navigation 最新库版本SavedStateViewModelFactory作为默认ViewModelProvider.Factory.

现在,您可以获取SavedStateHandle到您ViewModel可与持久/跨进程死亡恢复的东西帮助。

class MyViewModel(private val savedStateHandle: SavedStateHandle): ViewModel() {
    val someState: MutableLiveData<String> = savedStateHandle.getLiveData("someState")
}
Run Code Online (Sandbox Code Playgroud)

或者

class MyAndroidViewModel(application: Application, private val savedStateHandle: SavedStateHandle): AndroidViewModel(application) {
    val someState: MutableLiveData<String> = savedStateHandle.getLiveData("someState")
}
Run Code Online (Sandbox Code Playgroud)

这些将通过它们的默认构造函数工作,就像SavedStateViewModelFactory通过反射创建它们一样。

如果您需要 aSavedStateHandle和其他参数,那么ViewModelProvider.Factory您可以代替使用 default ,而不是使用 default ,而是从中扩展,AbstractSavedStateViewModelFactory这将为您提供一个SavedStateHandle实际工作并自动在进程死亡期间持续/恢复的参数。

val viewModel = ViewModelProvider(this, myAbstractSavedStateViewModelFactoryImpl).get(MyViewModel::class.java)
Run Code Online (Sandbox Code Playgroud)

或者用KTX的东西

private val viewModel by viewModels { myAbstractSavedStateViewModelFactoryImpl }
Run Code Online (Sandbox Code Playgroud)

您还可以将 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
        )
    })
}
Run Code Online (Sandbox Code Playgroud)

然后

class MyFragment: Fragment() {
    private val mySharedViewModel by navGraphSavedStateViewModels(R.id.registration_graph) { handle ->
        MySharedViewModel(handle)
    }
}
Run Code Online (Sandbox Code Playgroud)