Jens van de Wiel
05/31/2025, 3:40 PMOlivier Patry
05/31/2025, 4:15 PM@Composable
fun MyScreen(viewModel: MyViewModel) {
val myData by viewModel.myState.collectAsStateWithLifecycle(null)
LaunchedEffect(myData) {
if (myData == null) {
viewModel.fetchData()
}
}
when (myData) {
null,
MyUiState.Loading -> CircularProgressIndicator()
MyUiState.Error -> SomeErrorContent()
is MyUiState.Data -> SomeContent(myData) // cast as MyDataState
}
}
Given
sealed interface MyUiState {
object Loading : MyUiState
object Error : MyUiState
data class Data(val some: Data, ...) : MyUiState
}
class MyViewModel(...) : ViewModel() {
private val _myState = MutableStateFlow<MyUiState?>(null)
val myState = _myState.asStateFlow()
fun fetchData() {
viewModelScope.launch {
_myState.value = MyUiState.Loading
// usually extracted in a domain layer through a use case or stuff like that, or directly with a data layer repository depending on the complexity & chosen architecture
val result = withContext(Dispatchers.IO) {
try { // or use runCatching + Result depending on the goal
... compute result somehow
} catch (e: Exception) {
null
}
}
_myState.value = when (result) {
null -> MyUiState.Error
else -> MyUiState.Data(result.something)
}
}
}
}
Jens van de Wiel
05/31/2025, 4:15 PMOlivier Patry
05/31/2025, 4:16 PMOlivier Patry
05/31/2025, 4:17 PMcollectAsStateWithLifecycle
, if it's purely desktop and you only use Jetbrains APIs in the jvmMain
source set, you might only have .collectAsState
but this would be the sameOlivier Patry
05/31/2025, 4:21 PMrunCatching
_myState.value = withContext(Dispatchers.IO) {
runCatching { // or use runCatching + Result depending on the goal
... compute result somehow
}
}.fold(
onFailure = { e -> MyUiState.Error },
onSuccess = { result -> MyUiState.Data(result.something) },
)
Alex Styl
05/31/2025, 7:30 PMJens van de Wiel
05/31/2025, 8:20 PMAlexander Maryanovsky
05/31/2025, 10:53 PMArkadii Ivanov
06/01/2025, 1:04 PMinit {}
block or in doOnCreate {}
, lastly update your state with the fetched data.Arkadii Ivanov
06/01/2025, 1:05 PMJens van de Wiel
06/01/2025, 3:11 PMlouiscad
06/12/2025, 10:36 PMproduceState
with different states and the value onces loaded might seem fine, but you might want to handle retries, and it immediately becomes not so simple.louiscad
06/12/2025, 10:38 PM