Home > Software engineering >  can I use callbackFlow even though I have not a callBackListener
can I use callbackFlow even though I have not a callBackListener

Time:06-16

I'm using GraphQL to fetch the data from the server. The SDK is not suspendable, and I'm trying to use Clean Architecture. So I came up to return a Flow in my repository to allow the UseCases to fetch the server's response. So I have this code in my repository:

override fun singUp(model: SignUpModel): Flow<ResponseModel<SignUpServerResponse>> = callbackFlow {
            ...
          
            client.mutateGraph(signUpQuery)
                .enqueue(object : GraphCallResultCallback<Storefront.Mutation> {
                    override fun invoke(result: GraphCallResult<Storefront.Mutation>) {

                        if (result is GraphCallResult.Success) 
                            trySendBlocking(...).also { close() }
                        else 
                            trySendBlocking(...).also { close() }
                    }
                })
            awaitClose {}
        }

my questions are:

1- Do I need to call the close after each event? Obviously, I don't need the flow to be alive after I fetch the response from the server.

2- I removed awaitClose {}, and I got the error that this field is required and should be used to detach the CallBackListener, but in this case, I don't have one. Is it okay if I'm putting an empty awaitClose {} at the end?

3- I know the flow uses Channels in the background. I also implemented it by channels, is there any advantages ( performance, security, etc.) that I have to using CallBackFlow?

CodePudding user response:

You don't need to use callbackFlow here like mentioned in the comments. If you want to use singUp() method with coroutines you need to convert it to a suspend function. To convert a function, that has callbacks, to a suspend function suspendCoroutine and suspendCancellableCoroutine builders can be used. Example:

suspend fun singUp(model: SignUpModel): ResponseModel<SignUpServerResponse> = suspendCoroutine { continuation ->
        ...
      
        client.mutateGraph(signUpQuery)
            .enqueue(object : GraphCallResultCallback<Storefront.Mutation> {
                override fun invoke(result: GraphCallResult<Storefront.Mutation>) {

                    if (result is GraphCallResult.Success) 
                        continuation.resume(...) // resumes an execution of a coroutine, in which the `singUp` method was called
                    else 
                        continuation.resume(...)
                }
            })
}
  • Related