Home > database >  How to properly use firebase-firestore async calls
How to properly use firebase-firestore async calls

Time:03-03

I am working on my Final Year Project and I am really stuck on the decision should I use callbacks or coroutines of Kotlin. I created separate Module for the firebase where all its operations are done there weather its data retrieval or any other functionalities.

the problem is that whenever I return the user from the function it return null due than I understand it due to the async calls and after that I used call back for it like this:

fun getUserAsModel(callback: (User) -> Unit) {
    FirebaseAuth.getInstance().uid?.let {
        firestore.collection(Constants.FireCollections.USERS)
            .document(it)
            .get()
            .addOnSuccessListener { it1 ->
                val user = it1.toObject(User::class.java)?.let { it2 ->
                    callback(it2)
                }
            }
            .addOnFailureListener {
                Log.e(TAG, "In userModel()->", it)
                it.stackTrace
            }
    }
}

But I see in many forms that I should I use coroutines and now I am using this approach but it does not work:

fun getUser () : User? {
    var user:User? = null
    val collection = firestore.collection(Constants.FireCollections.USERS)
    val document = collection.document(FirebaseAuthRepository().getCurrentUserId())
    try {
        scope.launch {
            val snapshot = document.get().await()
            user = snapshot.toObject(User::class.java)
        }
    } catch (e:FirebaseFirestoreException) {
        Log.e(TAG, "In getUser() -> " ,e)
        e.stackTrace
    }
    return user
}

I am still stuck because every time I use getUser() I need to launch the scope of coroutines and this is really makes the code juncky.

I would like to know about your solution how should I properly implement this. Thanks

CodePudding user response:

You're recreating the same problem you had with the asynchronous call, since a coroutine is launched asynchronously. The correct way to do it with a coroutine is to make it a suspend function and directly return the user without launching another coroutine inside this function.

The function should look like this:

suspend fun getUser () : User? {
    val collection = firestore.collection(Constants.FireCollections.USERS)
    val document = collection.document(FirebaseAuthRepository().getCurrentUserId())
    return try { 
        val snapshot = document.get().await()
        snapshot.toObject(User::class.java)
    } catch (e: FirebaseFirestoreException) {
        Log.e(TAG, "In getUser() -> ", e)
        null
    }
}

Callbacks versus coroutines is a matter of preference. Coroutines are not trivial to learn, but once you do, your code will be cleaner-looking and easier to follow.

  • Related