Duplicate Display Screenshot Firestore Queries Screenshot
I am using Jetpack Compose + HiltViewModel + Firestore database
When I perform add action somehow the last entry is duplicated on LazyColumn.
The data is added correctly to the Firestore database [9604], but somehow the display is totally wrong [showing 2804 twice] until I restart the emulator or I rotate the device.
Below are the code that I think might be relevant.
@OptIn(ExperimentalLifecycleComposeApi::class)
@Composable
fun PatientsScreen(
modifier: Modifier = Modifier,
viewModel: PatientsViewModel = hiltViewModel()
) {
val patients = viewModel.patients.collectAsStateWithLifecycle(emptyList())
Column {
LazyColumn {
items(patients.value) { patientItem ->
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween
) {
Text(patientItem.pid, fontSize = 24.sp)
Text(patientItem.location, fontSize = 24.sp)
Button(
onClick = { viewModel.onAcknowledge(patient = patientItem) },
enabled = patientItem.status.equals("Activated"),
shape = RoundedCornerShape(30)
) {
if (patientItem.status.equals("Activated")) {
Text("Acknowledge")
} else {
Text(patientItem.status)
}
}
}
}
}
Button(
onClick = { viewModel.registerPatient() },
shape = CircleShape
)
{
Text("+", fontSize = 36.sp)
}
}
}
@HiltViewModel
class PatientsViewModel @Inject constructor (
private val storageService: StorageService,
) : ViewModel() {
val patients = storageService.patients
fun onAcknowledge(patient: Patient) {
viewModelScope.launch {
storageService.update(patient.copy(status = "Acknowledged"))
}
}
fun registerPatient() {
val patient = mutableStateOf(Patient())
val newId = Random.nextInt(0, 9999).toString().padStart(4, '0')
patient.value = patient.value.copy(pid = newId)
patient.value = patient.value.copy(status = "Unused")
viewModelScope.launch {
val newPatient = patient.value
storageService.add(newPatient)
}
}
}
class StorageServiceImpl
@Inject
constructor(private val firestore: FirebaseFirestore) : StorageService {
override val patients: Flow<List<Patient>>
get() =
currentCollection().snapshots().map { snap ->
snap.toObjects()
}
override suspend fun getPatient(patientId: String): Patient? =
currentCollection().document(patientId).get().await().toObject()
override suspend fun add(patient: Patient): String =
currentCollection().add(patient).await().id
override suspend fun update(patient: Patient) {
currentCollection().document(patient.id).set(patient).await()
}
override suspend fun delete(patientId: String) {
currentCollection().document(patientId).delete().await()
}
private fun currentCollection(): CollectionReference =
firestore.collection(PATIENT_COLLECTION)
companion object {
private const val PATIENT_COLLECTION = "patients"
}
}
The LazyColumn displaying the new entry registerPatient()
In case others encounter the same issue, this is due to my LazyColumn doesn't pass the key. After adding the key, the issue is solved. items(items = patients.value, key = { patientItem -> patientItem.pid })