Kotlin: elemento non aggiunto all'elenco [duplicato]

Aug 22 2020

Sto creando un'app per Android con kotlin, ma al momento sto affrontando uno strano problema. La funzione in cui il problema è questo:

private fun getName(uids:List<String>):List<String> {
        val nameList = mutableListOf<String>()
        for (uid in uids) {
            Firebase.firestore.collection("users").whereEqualTo("id", uid).get().addOnSuccessListener { documents ->
                    val name = documents.documents[0]["name"] as String
                    println("The name is $name") nameList.add(name) println("The namelist is $nameList")
                }
            println("The data above is $nameList") } println("The datahere is $nameList")
        return nameList.toList()
    }

Qui ho alcuni ID dell'utente e in base a questi ID sto recuperando il nome dal database Firebase Cloud Firestore, i dati vengono recuperati con successo e quando stampo la namelistprima volta all'interno del blocco di recupero, viene aggiunto un elemento. Tuttavia, quando stampo l' nameListesterno del blocco di recupero, vedo che l'elemento non si aggiunge. Ho allegato un'immagine.

Come puoi vedere l'elemento è stato aggiunto. Ma dopo di ciò, l'elemento scompare e l'elenco diventa vuoto.

Sono davvero confuso sul motivo per cui questo sta accadendo.

Risposte

2 aminography Aug 22 2020 at 08:32

La causa è che desideri che un lavoro asincrono agisca come uno di sincronizzazione. Come sappiamo, il recupero dei dati da firestoreè una procedura asincrona (attenzione a addOnSuccessListener). Quindi, quando la funzione ritorna nameList(così come l'ultima println), è vuota perché nessuno dei risultati di firestorenon è stato ancora recuperato!


Quando DocumentReference.get()restituisce un Taskoggetto è possibile attendere su di esso. Quindi, la tua funzione potrebbe essere qualcosa del genere:

@WorkerThread
private fun getName(uids: List<String>) {
    val nameList = mutableListOf<String>()
    for (uid in uids) {
        val task = Firebase.firestore.collection("users").whereEqualTo("id", uid).get()
        val documentSnapshot = Tasks.await(task)
        val name = documentSnapshot.documents[0]["name"] as String
        nameList.add(name)
    }
    nameList.toList()
}

Si noti che in questo caso, è necessario chiamare questa funzione in un thread di lavoro (non thread principale).