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