Jeff Lockhart
07/06/2023, 8:31 AMsuspendCancellableCoroutine
to suspend a coroutine awaiting the results of a callback API to resume the coroutine with:
val result = suspendCancellableCoroutine { continuation ->
callbackApi {
continuation.resume(it)
}
}
This works as expected the first time the code is called, but the second time the code is executed continuation.resume()
doesn't work. continuation.isActive
is false, continuation.isCompleted
and continuation.isCancelled
are true. Is it wrong to expect an active continuation after calling suspendCancellableCoroutine
? Even after wrapping the code in async
, launching a fresh coroutine, the continuation still isn't active the second time the code executes. What am I doing wrong?efemoney
07/06/2023, 10:24 AMefemoney
07/06/2023, 10:26 AMJeff Lockhart
07/06/2023, 3:28 PMJeff Lockhart
07/07/2023, 6:41 PMsuspendCancellableCoroutine
is used to suspend awaiting callback here. The failing tests were all calling this.
If I replace runTest
with runBlocking
and the withPagingDataDiffer
function with this:
suspend fun <T : Any> PagingData<T>.withPagingDataDiffer(
testScope: CoroutineScope,
diffCallback: DiffUtil.ItemCallback<T>,
block: AsyncPagingDataDiffer<T>.() -> Unit,
) {
val pagingDataDiffer = AsyncPagingDataDiffer(
diffCallback,
NoopListCallback,
mainDispatcher = Dispatchers.Default,
workerDispatcher = Dispatchers.Default,
)
val job = testScope.launch {
pagingDataDiffer.submitData(this@withPagingDataDiffer)
}
delay(100)
block(pagingDataDiffer)
job.cancel()
}
the tests now pass with the continuations behaving as expected.Jeff Lockhart
07/07/2023, 6:42 PMdelay(100)
awaiting the database operations to be completed. I'll have to see if there's a better way to replace this.Jeff Lockhart
07/20/2023, 7:02 PM