I’m just learning how to manage UI States. In the following example I’m using combine() for 2 of my use cases and they are collected when the app starts. But what if I want to collect a 3rd different use case when the user clicks a button, for example. How could I update the state in this case. Should I use a separate and different StateFlow? Thanks in advance!
val uiState: StateFlow<NewsUiState> =
combine(
getAllTopNewsUseCase(),
getNewsByKeywordUseCase(_keywordSearch.value)
) { latestNews, newsByKeyword ->
when {
latestNews.isNullOrEmpty() -> NewsUiState.Success(newsByKeyword = newsByKeyword)
newsByKeyword.isNullOrEmpty() -> NewsUiState.Success(latestNews = latestNews)
else -> NewsUiState.Success(latestNews, newsByKeyword)
}
}.catch {
NewsUiState.Error(it)
}.stateIn(
scope = viewModelScope,
started = SharingStarted.WhileSubscribed(5_000),
initialValue = NewsUiState.Loading
)
This is the sealed interface I defined to hold the state:
sealed interface NewsUiState {
object Loading: NewsUiState
data class Success(
val latestNews: List<NewsItem>? = null,
val newsByKeyword: List<NewsItem>? = null
): NewsUiState
data class Error(val throwable: Throwable): NewsUiState
}
And, if it’s useful this is how I produce state from my Screen:
val lifecycle = LocalLifecycleOwner.current.lifecycle
val uiState by produceState<NewsUiState>(
initialValue = NewsUiState.Loading,
key1 = lifecycle,
key2 = newsViewModel,
) {
lifecycle.repeatOnLifecycle(state = Lifecycle.State.STARTED) {
newsViewModel.uiState.collect { value = it }
}
}
when(uiState) {
is NewsUiState.Error -> TODO()
NewsUiState.Loading -> TODO()
is NewsUiState.Success -> TODO()
}