how would I turn this into something that uses cor...
# coroutines
o
how would I turn this into something that uses coroutines?
Copy code
class DetermineAuthStatus @Inject constructor(
    private val firebaseAuth: FirebaseAuth,
    private val populateUserPrefs: PopulateUserPrefs
) {
    operator fun invoke() = firebaseAuth.currentUser?.let { currentUser ->
        val subject = SingleSubject.create<Boolean>()
        subject
            .hide()
            .doOnSubscribe {
                currentUser.getIdToken(false)
                    .addOnSuccessListener { task ->
                        populateUserPrefs(currentUser, task.token)
                        subject.onSuccess(true)
                    }
                    .addOnFailureListener {
                        subject.onError(it)
                    }
            }
    } ?: Single.just(false)
}
r
You could use `suspendCoroutine`: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.coroutines/suspend-coroutine.html Something like:
Copy code
val currentUser = firebaseAuth.currentUser ?: return false
suspendCoroutine { cont ->
    currentUser.getIdToken(false).addOnSuccessListener { task ->
        populateUserPrefs(currentUser, task.token)
        cont.resume(true)
    }.addOnFailureListener {
        cont.resumeWithException(it)
    }
}
o
well thank you very much for scrolling up and finding this and taking the time to answer it, I will be looking at it tonight and seeing how it behaves, thanks a lot
👍🏻 1
ok so I’m just looking at it now, and I have some questions it looks like this “shape” or way of doing it can be suitable for all my usecases that just go out and do something and return something else depending on what it found, or is this something specific to what you saw the original code was doing? how do I treat this back in where i want to invoke it?
Copy code
val authenticated = determineAuthStatus.invoke()

if (authenticated) do something else do something else?
what about when it’s an exception instead of the boolean im expecting? do I just place it in a try/catch all the time to make sure i catch these exceptions?
r
it looks like this “shape” or way of doing it can be suitable for all my usecases that just go out and do something and return something else depending on what it found, or is this something specific to what you saw the original code was doing?
Yeah correct you can use
suspendCoroutine
to convert any kind of “single result callback” to a suspend function.
how do I treat this back in where i want to invoke it?
What do you mean exactly?
what about when it’s an exception instead of the boolean im expecting?
do I just place it in a try/catch all the time to make sure i catch these exceptions?
It depends on the use case, you could return the exception from your suspend function. In that case you should pass it to the
resume
call. Or you could return
Unit
and have the function throw the exception like in my previous example.
o
your function actually does the first suggestion, pass it to the resume call
r
In this case it uses
resumeWithException
, which will throw the exception. So you should wrap the call in a try-catch to handle them.
o
clear, and that’s not like ugly or anything? I see it’s perfectly fine to do this honestly, having the try catch at the call place instead of where the value is received
r
I don't think it's ugly. That said there might be a more elegant way to do this, but that depends on what you are trying to accomplish and from where you are going to use this function.
o
well it’s just inside the viewmodel for the main screen, if the user turns out to be authenticated, show the home screen, otherwise show the auth screen (sign in/ sign up)
r
In that case I would probably just log the exception and resume with
false
.
o
makes sense!
by the way, I am reading a really great book by Raywenderlich called “Kotlin Coroutines by Tutorials”, super well written and thorough, I just reached
suspendCoroutine
which you gave me the shortcut to 🙂
👍🏻 1