Kotlin:要素がリストに追加されていません[重複]

Aug 22 2020

kotlinでAndroidアプリを作成していますが、現在、奇妙な問題に直面しています。問題がこれである関数:

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

ここにユーザーのIDがいくつかあり、これらのIDに基づいて、Firebase Cloud Firestoreデータベースから名前をフェッチしています。データは正常にフェッチされておりnamelist、フェッチブロック内で初めて印刷するときに、要素が追加されています。ただし、nameListフェッチブロックの外側を印刷すると、要素が追加されないことがわかります。画像を添付しました。

ご覧のとおり、要素が追加されています。しかしその後、要素は消え、リストは空になります。

なぜこれが起こっているのか、私は本当に混乱しています。

回答

2 aminography Aug 22 2020 at 08:32

原因は、非同期ジョブを同期ジョブとして機能させたいためです。私たちが知っているように、からのそのようなデータの取得firestoreは非同期プロシージャです(に注意してくださいaddOnSuccessListener)。したがって、関数がnameList(最後と同様に)戻るとき、printlnからの結果のいずれかがfirestoreまだ取得されていないため、関数は空です!


オブジェクトをDocumentReference.get()返すので、Taskそれを待つことができます。したがって、関数は次のようになります。

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

この場合、この関数は(メインスレッドではなく)ワーカースレッドで呼び出す必要があることに注意してください。