0

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()

David Tio
  • 1
  • 2
  • Hey, if you've answered your own question, please create and post an answer rather than just leaving it in a comment, as doing so provides more help to others when searching for an answer the same problem/question. – undermark5 Dec 25 '22 at 23:12
  • I actually were not aware that I was able to post an answer. Thank you @undermark5 for pointing it out. I have repost as answer – David Tio Dec 27 '22 at 06:03

1 Answers1

0

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 })

David Tio
  • 1
  • 2
  • 1
    Would be super awesome to inclde some links to some documentation or resources that helped you come to your solution, not required, but something that explains why adding key solved the problem would be good. – undermark5 Dec 27 '22 at 07:59