问题描述
因为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}")
}
}