Jetpack compose 中的活动视图模型

Abh*_*bhi 7 android android-jetpack-compose

在片段中,我们有

private val activityViewModel: MainActivityViewModel by activityViewModels()
private val fragmentViewModel: MainFragmentViewModel by viewModels()
Run Code Online (Sandbox Code Playgroud)

获取整个应用程序中的共享视图模型(活动视图模型)和视图特定视图模型(片段视图模型)的实例。

我正在迁移以作曲。

如何在jetpack compose中获得两个具有不同范围的视图模型?

文档中,我可以看到这一行,

viewModel() 返回一个现有的 ViewModel 或在给定范围内创建一个新的 ViewModel。

但是,如何指定视图模型的范围?

PS
我已经解决了这个类似的问题,但没有任何答案。

Phi*_*hov 6

通常,在单个组合树中(例如在setContent内容中),有一个在所有子组合之间共享的视图模型范围。

如果需要,您可以使用以下命令覆盖它LocalViewModelStoreOwner

CompositionLocalProvider(
    LocalViewModelStoreOwner provides viewModelStoreOwner
) {
    NextComposable()
}
Run Code Online (Sandbox Code Playgroud)

Compose Navigation 会为每个导航目的地覆盖它。请参阅此答案,了解如何在导航目的地之间共享它。


Lio*_*and 5

详细说明@Pylyp Dukhov。由于可以直接在树中更改默认提供程序,因此可以创建一个viewModel在特定ViewModelStore.

我已经为此制定了要点。

内容如下:

/** Try to fetch a viewModel in [store] */
@Composable
inline fun <reified T : ViewModel, S : ViewModelStoreOwner> viewModelInStore(store: S): Result<T> =
    runCatching {
        var result: Result<T>? = null
        CompositionLocalProvider(LocalViewModelStoreOwner provides store) {
            result = runCatching { viewModel(T::class.java) }
        }
        result!!.getOrThrow()
    }

/** Try to fetch a viewModel with current context (i.e. activity)  */
@Composable
inline fun <reified T : ViewModel> safeActivityViewModel(): Result<T> = runCatching {
    val activity = LocalContext.current as? ViewModelStoreOwner
        ?: throw IllegalStateException("Current context is not a viewModelStoreOwner.")
    return viewModelInStore(activity)
}

/** Force fetch a viewModel inside context's viewModelStore */
@Composable
inline fun <reified T : ViewModel> activityViewModel(): T = safeActivityViewModel<T>().getOrThrow()
Run Code Online (Sandbox Code Playgroud)

在活动存储中获取 viewModel 就像从默认树的存储中获取 viewModel 一样简单。

@Composable
fun MyComposeElement(
    fragmentViewModel: ComposeViewModel = viewModel(),
    activityViewModel: ComposeViewModel = activityViewModel()
) {
    assert(fragmentViewModel != activityViewModel)
    assert(fragmentViewModel == viewModel<ComposeViewModel>())
    assert(activityViewModel == activityViewModel<ComposeViewModel>())
}
Run Code Online (Sandbox Code Playgroud)