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(...)
}
})
}