ARTICLE AD BOX
I am currently learning Jetpack Compose and trying to implement a loading indicator while data is being loaded.
I am managing the UI state using state management (StateFlow/MutableStateFlow). My goal is to show a loader while the data is loading and display the content once the data is loaded.
However, the loader is not showing while the data is loading.
What is the correct way to manage state so that the loader is displayed during the loading process and the UI updates correctly once the data is available?
Retrofit
object FakeApiClient { val apiService: GetDataService by lazy { object : GetDataService { override suspend fun getData(): List<UserDataModel> { delay(2.seconds) return List(100) { UserDataModel("User #$it", "$it", "[email protected]") } } } } } interface GetDataService { @GET("users") suspend fun getData() : List<UserDataModel> } class UserRepository(val api: GetDataService) { suspend fun getUser() : List<UserDataModel> { return api.getData() } } @Composable fun HomeScreen(modifier: Modifier,viewModel: HomeViewModel = viewModel()) { val users = viewModel.uiState.collectAsState().value when(users) { is HomeUIState.Loading -> { CircularProgressIndicator() } is HomeUIState.NoData -> { Text("No data found") } is HomeUIState.Error -> { val errormsg = users.error Text(errormsg) } is HomeUIState.Success ->{ val list = users.list Column() { LazyColumn() { items(list.size) { index -> Text(list[index].name) } } } } } } class HomeViewModel( val userRepo : UserRepository = UserRepository(FakeApiClient.apiService)) : ViewModel() { private val _uiState = MutableStateFlow<HomeUIState>(HomeUIState.Loading) val uiState : StateFlow<HomeUIState> = _uiState private val _uiString = MutableStateFlow("") val uiString : StateFlow<String> = _uiString init { loadData() } private fun loadData() { viewModelScope.launch{ _uiState.value = HomeUIState.Loading try { val users = userRepo.getUser() if(users.isEmpty()) { _uiState.value = HomeUIState.NoData } else{ _uiState.value = HomeUIState.Success(users) } } catch (e: Exception) { _uiState.value = HomeUIState.Error(e.localizedMessage ?: "Something went wrong") } } } } data class UserDataModel(val name : String,val username : String, val email : String) sealed interface HomeUIState { data object Loading : HomeUIState data object NoData : HomeUIState data class Success(val list: List<UserDataModel>) : HomeUIState data class Error(val error: String) : HomeUIState } implementation("com.squareup.retrofit2:retrofit:2.9.0") implementation("com.squareup.okhttp3:okhttp:4.9.0") implementation("com.squareup.okhttp3:logging-interceptor:4.9.0") implementation("com.squareup.retrofit2:converter-gson:2.9.0") implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.6.2") testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.7.3") testImplementation("io.mockk:mockk:1.13.8")