I have the intention of converting the structure I am currently using to flow. It may sound silly or irrelevant to you.
Let me explain to you the structure:
- I have an object named
BleDataSource. For example, it has a function like below.
fun performConnect(device: BluetoothDevice, result: ((Resource<BleOperationResult>) -> Unit)) {
enqueueOperation(Connect(device, result))
}
fun callback() {
if ( operation is Connect ) {
if ( erroroccured )
operation.result(Resource.Error("error"))
else
operation.result(Resource.Loading())
}
}
fun onetherCallback() {
if ( operation is Connect ) {
operation.result(Resource.Success())
}
}
-
This function saves to the job queue and connects to the device when it’s turn. I can report the current status of the job(For example Loading, Success Or Error) because I also save the
result. -
From repository i am using this function as below:
override fun connect(device: BluetoothDevice, result: (Resource<BleOperationResult>) -> Unit) {
handler.performConnect(device, result)
}
But I want it to return as flow from the repository.
override fun connect(device: BluetoothDevice): Flow<Resource<BleOperationResult> {
handler.performConnect(device) {
}
}
How can I do that? (according to recommandation i can also edit the BleDataSource class)
>Solution :
If I understand correctly, it looks like a classic case of converting a "multi-shot" callback function to a flow.
This can be done using callbackFlow:
fun BleDataSource.connect(device: BluetoothDevice): Flow<Resource<BleOperationResult>> = callbackFlow {
performConnect(device) { res ->
channel.send(res) // or trySend + error handling
}
awaitClose()
}
The problem is that I don’t see a way to unregister the callback from the API you provided. Once you called performConnect with a lambda, it looks like this lambda listener cannot be removed. If there is a way to do that, you should do it in the lambda passed to awaitClose { ... }.