如何第一步完成Firestore的值,然后第二步让获得的值发送到第二段代码?

问题描述

因为Firestore的.addSnapshotListener是异步的。我该如何第一步从Firestore获取imgsGroupIds,然后第二步将imgsGroupIds发送到trackImageViewModel.getUserTrackedImgs(imgsGroupIds !!)?

换句话说,如何让第1步完成,然后在第1步获得imgsGroupIds之后运行第2步?

runBlocking{
            val imgsGroupIds: MutableList<String>? = mutableListOf()

            val deferred = async {
                Log.d(TAG,"CoroutineScope(Dispatchers.IO): Thread:${Thread.currentThread().name}")
                Firebase.firestore
                    .collection("userData")
                    .document(uid!!)
                    .collection("trackGroupId")
                    .addSnapshotListener { querySnapshot: QuerySnapshot?,error: FirebaseFirestoreException? ->
                        Log.d(TAG,"addSnapshotListener: Thread:${Thread.currentThread().name}")
                        Log.d(TAG,"onViewCreated: FirebaseFirestoreException: $error")
                        querySnapshot?.forEach {
                            val imgsGroupId = it.id
                            Log.d(TAG,"onViewCreated: imgsGroupId = $imgsGroupId")
                            imgsGroupIds!!.add(imgsGroupId)
                        }
                    }
            }
            deferred.await()

            Log.d(
                TAG,"trackImageViewModel.getUserTrackedImgs: Thread:${Thread.currentThread().name}"
            )
            Log.d(TAG,"onViewCreated: imgsGroupIds = $imgsGroupIds")
            if (imgsGroupIds != null) {
                trackImageViewModel.getUserTrackedImgs(imgsGroupIds)
                    .observe(viewLifecycleOwner,Observer {
                        tracked_imgs_recycler_view.apply {
                            setHasFixedSize(true)
                            layoutManager = LinearLayoutManager(requireContext())
                            val detailRecyclerAdapter =
                                DetailRecyclerAdapter(requireContext(),it).apply {
                                    notifyDataSetChanged()
                                }
                            adapter = detailRecyclerAdapter

                        }
                    })
            }


        }

解决方法

您可以使用协程Flow。在核心模块中。

这是Firestore中的“联系人”文档: Firestore collection/documents

模块类联系人:

class Contact(var name: String) {
    constructor(): this("John Doe")
}

通过使用callbackFlow {}将Firestore预先设计为:

fun getContacts() = callbackFlow<Contact> {
    val ref = FirebaseFirestore.getInstance().collection("contacts")
    val eventListener = ref.addSnapshotListener { value,error ->
        if (error != null) {
            Log.w(TAG,"getContacts: ",error )
        } else {
            for (doc in value!!) {
                val contact = doc.toObject(Contact::class.java)
                this@callbackFlow.sendBlocking(contact)
            }
        }
    }
    awaitClose {
        eventListener.remove()
    }
}

以下是实际读取和获取的数据:

    CoroutineScope(Dispatchers.IO).launch {
        getContacts().collect {
            Log.d(TAG,"onCreate: ${it.name}")
        }
    }

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...