This is the data class to be used for data loading from firestore db.
If you are using flow to load initial data, you must make sure it only the fetch only run once.
class CardViewModel : ViewModel() { val itemsFlow = flow { val items = MutableList((1..100).random()) { index -> index } emit(items) }}
Put a timestamp to check if the data is only load once.
fun CardScreen(viewModel: CardViewModel = viewModel()) { val items by viewModel.itemsFlow.collectAsState(initial = emptyList()) Text("Items: ${items.size}, Time: ${LocalTime.now()}")}
If you use a function, it will cause compose infinite loop (the timestamp will update forever).
class CardViewModel : ViewModel() { private val db = Firebase.firestore fun getItems() = flow { val items = MutableList((1..100).random()) { index -> index } emit(items) }}
fun CardScreen(viewModel: CardViewModel = viewModel()) { val items by viewModel.getItems().collectAsState(initial = emptyList()) Text("Items: ${items.size}, Time: ${LocalTime.now()}")}
If you must use a function, you need to call the function in LaunchedEffect
.
fun CardScreen(viewModel: CardViewModel = viewModel()) { var items by remember { mutableStateOf<List<Int>>( emptyList()) } LaunchedEffect(true) { // only launch once viewModel.getItems().collect { items = it } } Text("Items: ${items.size}, Time: ${LocalTime.now()}")}
Assuming you need to load initial data, and perform a fetch on every click of a button.
fun CardScreen(viewModel: CardViewModel = viewModel()) { var refreshCount by remember { mutableStateOf(0) } var items by remember { mutableStateOf<List<Int>>( emptyList()) } LaunchedEffect(refreshCount) { // run if refreshCount is updated // you can choose to generate items based on refreshCount viewModel.getItems().collect { items = it } } // button click will Button(onClick = { refreshCount += 1 }) { Text("Refresh") } Text("Items: ${items.size}, Time: ${LocalTime.now()}")}
Refer to Jetpack Compose Load Data (Initial on Show) using Flow or Coroutines.