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.