My goal here is to have loadInformationFromFirestore, which reads data from a Firestore database, complete before the code after it (here just a Timber logging message) is executed. When I run getGroupSummaries, these are the logging messages I see:
After loadUserInformationFromFirestore in runBlocking
After loadUserInformationFromFirestore after runBlocking
In LoadUserInformationFromFirestore
This says to me that "runBlocking" is not blocking at all -- the runBlocking returns before LoadUserInformationFromFirestore completes. Any advice would be appreciated.
var mFirestore: FirebaseFirestore? = null
fun getGroupSummaries(groupInfo: GroupInformation, adminUserInfo: UserInformation) {
mFirestore = FirebaseFirestore.getInstance()
val uid = "3iHWCsGmKvfq4w9OgDNWZsSs8wy2"
runBlocking {
val loadUserInformationJob = viewModelScope.launch { loadUserInformationFromFirestore(uid) }
loadUserInformationJob.join()
Timber.d("After loadUserInformationFromFirestore in runBlocking")
}
Timber.d("After loadUserInformationFromFirestore after runBlocking")
}
suspend fun loadUserInformationFromFirestore(uid: String) {
try {
// Get document from Firestore
val docRef =
mFirestore!!.collection("Users").document(uid).collection("UserProfile").document(uid)
docRef.get().addOnCompleteListener { task ->
if (task.isSuccessful) {
val document = task.result
if (document.exists()) {
Timber.d("In LoadUserInformationFromFirestore")
} else if (!document.exists()) {
Timber.e(
"In LoadInformationFromFirestore, User document does not exist. Send user through into questions."
)
} else {
Timber.e("In LoadInformationFromFirestore, Error loading user document")
}
} else {
Timber.e(
"In LoadInformationFromFirestore, get Firestore failed with ",
task.exception
)
}
}
} catch (e: Exception) {
Timber.w("Error getting Firebase User", e)
}
}
I think the issue is related to the asynchronous nature of Firestore callbacks. The
addOnCompleteListenercallback insideloadUserInformationFromFirestoreis asynchronous, and runBlocking doesn't wait for it to complete.You can use
suspendCoroutineorsuspendCancellableCoroutineto convert the asynchronous Firestore task into a suspendable coroutine. This way, you can ensure that the runBlocking coroutine will wait for the Firestore task to complete before moving on.See here:
Here, the runBlocking coroutine will wait for the Firestore task to complete before moving on to the next line. Additionally, it handles exceptions and provides a more structured way of returning the result.
Hope it helps!