在 Android ViewModel 中操作密封的 UiState 类

问题描述 投票:0回答:1

我正在阅读Android UI 层速成课程,其中建议通过密封类对复杂的 UI 状态进行建模,例如像这样:

我会以

的形式向 UI (Compose) 公开这样的状态
private val _uiState = MutableStateFlow<HomeUiState>(HomeUiState.NoPosts()) // flow of type HomeUiState
val uiState = _uiState.asStateFlow()

现在,如果我从 UI 触发业务逻辑,例如

// in the UI
when (uiState) {
    is HasPosts -> { // smart cast from interface type to concrete data class HomeUiState.HasPosts
        // Action triggered e.g. by a button
        viewModel.refreshPosts()
    }
}

似乎我总是必须在 ViewModel 中进行类型转换,然后才能访问触发函数的 UiState 特定的成员。

// ViewModel
fun refreshPosts() {
    if(uiState.value is HomeUiState.HasPosts) {
        // here I can access HasPosts's specfic members like postsFeed
        uiState.postsFeed.refresh()
    }
}

我无法想象我必须在每个 ViewModel 函数中进行类型转换才能访问 UiState 的属性。例如。想想像

UiState.Loading
UiState.Success
这样的 UiState:ViewModel 中的大多数函数都会在
UiState.Success
状态上运行,仅仅因为我有另一个 UiState,我需要在任何地方进行转换?

我肯定错过了一些东西?!

android kotlin android-jetpack-compose android-viewmodel
1个回答
0
投票

只有观察者中的

when
块知道
uiState.value
属于特定类型。当您调用
viewModel.refreshPosts()
时,基础值可能已更改,因此您需要再次确认类型。

相反,假设这是要更改某些“刷新”按钮的状态,请使用观察者块来更新您的单击处理,并将强类型值传递给您的

ViewModel
方法:

fun refreshPosts(feed: PostsFeed) {
  feed.refresh()
}

然后你的观察者可以直接传入智能铸造的对象:

when (uiState) {
  is HasPosts -> 
    refreshButton.setOnClickListener { 
      viewModel.refreshPosts(uiState.postsFeed)
    }
}

我假设这是一个简化的示例,但在您的情况下,您可能根本不需要

refreshPosts
方法,而应该直接调用
uiState.postsFeed.refresh()

© www.soinside.com 2019 - 2024. All rights reserved.