ursus
11/09/2019, 10:58 PMbholota
11/09/2019, 11:19 PMursus
11/09/2019, 11:22 PMursus
11/09/2019, 11:24 PMbholota
11/09/2019, 11:28 PMursus
11/09/2019, 11:31 PMSingle.fromCallable { calculation1() }
.flatMap { calculation2() }
ursus
11/09/2019, 11:31 PMursus
11/09/2019, 11:32 PMlaunch {
calculation1()
calculation2()
}
ursus
11/09/2019, 11:32 PMbholota
11/09/2019, 11:34 PMursus
11/09/2019, 11:35 PMbholota
11/09/2019, 11:46 PMursus
11/10/2019, 12:00 AMbholota
11/10/2019, 12:03 AMyield()
or delay()
that will throw CancellationExceptionbholota
11/10/2019, 12:05 AMisActive
but yield()
also allows suspension (or throws exception)ursus
11/10/2019, 12:09 AMbholota
11/10/2019, 12:14 AMbholota
11/10/2019, 12:14 AMursus
11/10/2019, 12:25 AMinterface Api {
@GET
suspend fun foo(@Url url: String): Foo
}
class ApiClient(private val api: Api) {
suspend fun whatever(url: String): Whatever {
val foo = api.foo(url)
val bar = blockingCode1(foo)
val whatever = blockingCode2(bar)
return whatever
}
fun blockingCode1(foo: Foo) {
...
}
fun blockingCode2(bar: Bar) {
...
}
}
ursus
11/10/2019, 12:25 AMursus
11/10/2019, 12:26 AMwhatever
I dont see this.isActivebholota
11/10/2019, 12:32 AMbholota
11/10/2019, 12:33 AMwhatever
shouldn't handle cancellation, it's caller responsibility.ursus
11/10/2019, 12:38 AMbholota
11/10/2019, 12:46 AMfun CoroutineScope.whatever(url: String): Whatever {
val foo = api.foo(url)
val bar = blockingCode1(foo)
if (isActive) throwOrReturnDefault()
val whatever = blockingCode2(bar)
return whatever
}
bholota
11/10/2019, 12:47 AMursus
11/10/2019, 12:56 AMoctylFractal
11/10/2019, 12:57 AMflow { emit(yourCallable()) }
octylFractal
11/10/2019, 12:58 AMursus
11/10/2019, 12:58 AMoctylFractal
11/10/2019, 12:58 AM.flowOn(<http://Dispatchers.IO|Dispatchers.IO>)
afterwardoctylFractal
11/10/2019, 1:00 AMcoroutineContext[Job]!!.isActive
ursus
11/10/2019, 1:01 AMursus
11/10/2019, 1:01 AMSingle.fromCallable { calculation1() }
.flatMap { calculation2() }
octylFractal
11/10/2019, 1:03 AMcalculation2()
to run if the code was in calculation1()
when cancelled?ursus
11/10/2019, 1:07 AMSingle.fromCallable { calculation1() }
.flatMap { calculation2() }
and this gets disposed mid calculation1, then yes it will run to completion because its blocking, however calculation2 wont get executed
If I port it like this
val job = scope.launch {
calculation1()
calculation2()
}
and job.cancel() mid calculation1, then calculation2 WILL get executed after calculation1 completesoctylFractal
11/10/2019, 1:09 AMif (!coroutineContext[Job]!!.isActive) throw CancellationException()
or just plain yield()
(which is also cancellable) between them, and it will workursus
11/10/2019, 1:19 AMursus
11/10/2019, 1:20 AMDefaultDispatcher-worker-X
, is that okay? in rx io would be called io worker etcbholota
11/10/2019, 1:21 AMursus
11/10/2019, 1:46 AMgildor
11/10/2019, 3:13 AMursus
11/10/2019, 3:16 AMgildor
11/10/2019, 3:16 AMursus
11/10/2019, 3:17 AMgildor
11/10/2019, 3:17 AMursus
11/10/2019, 3:18 AMgildor
11/10/2019, 3:18 AMgildor
11/10/2019, 3:20 AMgildor
11/10/2019, 3:20 AMNo need to do that, there is!coroutineContext[Job]!!.isActive
coroutineContext.isActive
extension propertygildor
11/10/2019, 3:21 AMgildor
11/10/2019, 3:23 AMursus
11/10/2019, 3:23 AMursus
11/10/2019, 3:25 AMprivate suspend fun foo() {
return withContext(<http://Dispatchers.IO|Dispatchers.IO>) {
...
while(isActive) {
}
}
}
like this?gildor
11/10/2019, 3:26 AMursus
11/10/2019, 4:30 AMoctylFractal
11/10/2019, 4:36 AMursus
11/10/2019, 5:02 AMoctylFractal
11/10/2019, 5:03 AMcoroutineScope { }
ursus
11/10/2019, 5:27 AMoctylFractal
11/10/2019, 5:30 AMcoroutineContext[Job]
gildor
11/10/2019, 10:11 AMGuys, its there doOnDispose equivalent? So I can easily see that the coroutine was canceled?As it was said before, direct equivalent is invokeOmCompletion, but you probably don't need this (except if you just need some side effect), the easiest and most flexible way is just use try/catch and catch CancellationException, so you can even control invocation flow
ursus
11/10/2019, 3:40 PMgildor
11/10/2019, 3:50 PM