Been trying to figure this out for two days and I'm at my wits end.
I have a ViewModel
data class ExampleUIState(
val samples: List<Sample> = emptyList(),
val isLoading: Boolean = false,
val isError: Boolean = false,
)
class ExampleViewModel(
private val section: String,
private val exampleRepository: ExampleRepository = ExampleRepository()
) : ViewModel() {
private val _uiState = MutableStateFlow(ExampleUIState())
val uiState: StateFlow<ExampleUIState> = _uiState.asStateFlow()
init {
viewModelScope.launch(Dispatchers.IO) {
_uiState.update { it.copy(isLoading = true) }
val samplesList = exampleRepository.getSamplesBySection(section)
if (samplesList.isNotEmpty()) {
_uiState.update { it.copy(isLoading = false) }
_uiState.update { it.copy(samples = samplesList) }
}
}
}
}
and a composable
@Composable
fun ExamplesScreen(
navController: NavController,
section: String?,
viewModel: ExampleViewModel = ExampleViewModel(section!!)
) {
val uiState by viewModel.uiState.collectAsStateWithLifecycle()
Column {
CustomTopAppBar(navController = navController, title = "Ejemplos", showBackIcon = true)
if (uiState.isLoading) {
CircularProgressIndicator()
} else {
for (sample in uiState.samples) {
Text(sample.section)
}
}
}
}
When I run the navigate to the composable ExampleScreen
, I would like the ViewModel to download network data once and then not refresh. However when I navigate it constantly refreshes, flickering back and forth from CircularProgressIndicator
to the list of Text
. I cannot for the life of me figure out why, does anybody know?
The reason it reruns the
init
block is because I was initializing the ViewModel in the copmosable, so everytime the composable refreshes (which happens a lot) it reinitializes the ViewModel.I'm using navigation to get to the screen, so I instantiated the ViewModel in my NavGraph and passed it to
ExamplesScreen
. Works perfectly now.