arnaud.giuliani
03/20/2019, 3:08 PMstructured concurrency
. If I understand, the thing is to ensure that we reuse a proper CoroutineScope
instead of launching coroutines in the `Global`f scope. Then here is my question. I have 2 components: A
& B
. My component A
initiate a coroutine scope and I can run functions against that. How do I share/propagate it to my component B
on which I want to call functions.
class A {
val coroutineContext: CoroutineContext ...
}
class B {
fun myFunction(){
// run with A.coroutineContext?
}
}
Do we have to pass the coroutineContext
as an argument to any call of B
?bdawg.io
03/20/2019, 4:04 PMA
implement CoroutineScope
and then inject an instance of A
into B
class A : CoroutineScope {
override val coroutineContext: CoroutineContext ...
}
class B(private val a: A) {
fun myFunction() {
a.launch { ... }
}
}
gildor
03/20/2019, 4:06 PMarnaud.giuliani
03/20/2019, 4:07 PMgildor
03/20/2019, 4:11 PMarnaud.giuliani
03/20/2019, 4:11 PMgildor
03/20/2019, 4:11 PMarnaud.giuliani
03/20/2019, 4:12 PMgildor
03/20/2019, 4:12 PMarnaud.giuliani
03/20/2019, 4:12 PMghedeon
03/20/2019, 4:14 PMwithContext
. No need to pass CoroutineScope.gildor
03/20/2019, 4:14 PMarnaud.giuliani
03/20/2019, 4:16 PMgildor
03/20/2019, 4:16 PMarnaud.giuliani
03/20/2019, 4:16 PMA
and subcomponents called from A
are suspending functionsghedeon
03/20/2019, 4:16 PMarnaud.giuliani
03/20/2019, 4:16 PMA
start a coroutines in backgroundgildor
03/20/2019, 4:17 PMarnaud.giuliani
03/20/2019, 4:18 PMgildor
03/20/2019, 4:18 PMghedeon
03/20/2019, 4:19 PMoverride val coroutineContext: CoroutineContext = job + Dispatchers.Main
In B:
suspend fun foo(){
withContext(<http://Dispatchers.IO|Dispatchers.IO>){ some work }
}
For channels you'd need to pass the scope.arnaud.giuliani
03/20/2019, 4:19 PMgildor
03/20/2019, 4:19 PMarnaud.giuliani
03/20/2019, 4:20 PMgildor
03/20/2019, 4:20 PMarnaud.giuliani
03/20/2019, 4:20 PMgildor
03/20/2019, 4:20 PMarnaud.giuliani
03/20/2019, 4:26 PMproduce
directly from a suspending functionclass A(val b : B) {
val rootJob = Job()
val coroutineContext = rootJob + <http://Dispatchers.dispatcherConfiguration.io|Dispatchers.dispatcherConfiguration.io>()
fun runMe() = coroutineContext.launch {
b.runMyChannel().consumeEach { myBooleanValue ->
// have incoming data
}
}
}
class B {
suspend fun runMyChannel() = Channel<Boolean>{
val channel = Channel<Boolean>()
Global.async {
// send a boolean value in a async way
val myBooleanValue = true
channel.send(myBooleanValue)
}
return channel
}
}
Global.async
to send data in a async way?gildor
03/20/2019, 4:32 PMI can’t useYes, this is what I mentioned above, you need some scopedirectly from a suspending functionproduce
arnaud.giuliani
03/20/2019, 4:33 PMgildor
03/20/2019, 4:33 PMarnaud.giuliani
03/20/2019, 4:34 PMgildor
03/20/2019, 4:34 PMarnaud.giuliani
03/20/2019, 4:34 PMB
have its own scope?B
to ensure that if we cancel A
we cancel cal to B
gildor
03/20/2019, 4:35 PMarnaud.giuliani
03/20/2019, 4:35 PMr4zzz4k
03/20/2019, 4:36 PMonBindViewHolder
of RecyclerView.Adapter
, I have to pass `Fragment`s scope to the adapter explicitly, right?arnaud.giuliani
03/20/2019, 4:36 PMB
I have old async API with callbacksr4zzz4k
03/20/2019, 4:37 PMclass MyAdapter(coroutineScole: CoroutineScope): RecyclerView.Adapter<...>(), CoroutineScope by coroutineScope {
should do?gildor
03/20/2019, 4:37 PMarnaud.giuliani
03/20/2019, 4:38 PMr4zzz4k
03/20/2019, 4:38 PMgildor
03/20/2019, 4:38 PMarnaud.giuliani
03/20/2019, 4:39 PMgildor
03/20/2019, 4:40 PMIt's not incorrect, it's just explicit about it's context. IIRCI'm not sure that it is the same tho, maybe, but it's not enough context to be sure
arnaud.giuliani
03/20/2019, 4:41 PMuser.getIdToken()
.addOnCompleteListener { task ->
// send my data here, but in other thread
}
gildor
03/20/2019, 4:41 PMarnaud.giuliani
03/20/2019, 4:42 PMgildor
03/20/2019, 4:42 PMarnaud.giuliani
03/20/2019, 4:42 PMr4zzz4k
03/20/2019, 4:42 PMarnaud.giuliani
03/20/2019, 4:43 PMgildor
03/20/2019, 4:43 PMr4zzz4k
03/20/2019, 4:44 PMgildor
03/20/2019, 4:44 PMarnaud.giuliani
03/20/2019, 4:45 PMkotlinx-coroutines-play-services
will clearly help 👍Wrapping callbacks
also 👍r4zzz4k
03/20/2019, 4:48 PMgildor
03/20/2019, 4:50 PMr4zzz4k
03/20/2019, 4:54 PMChannel
itself or provides a channel where it emits events observed in upstream (and vice versa).gildor
03/20/2019, 4:59 PMarnaud.giuliani
03/20/2019, 5:02 PMDico
03/20/2019, 6:26 PMclass B {
fun CoroutineScope.runMyChannel() = Channel<Boolean>().also { launch { it.send(true) } }
gildor
03/20/2019, 11:35 PMbdawg.io
03/21/2019, 3:25 AMproduce
closes the channel when the produce
coroutine returnsgildor
03/21/2019, 3:35 AMDico
03/21/2019, 4:04 AMgildor
03/21/2019, 4:05 AMDico
03/21/2019, 4:05 AMoffer
😂 no CoroutineScope neededAntanas A.
03/21/2019, 8:50 AMarnaud.giuliani
03/21/2019, 9:19 AMAntanas A.
03/21/2019, 9:22 AMgildor
03/21/2019, 9:23 AMif A’s object scope will be cancelled all invocations deep inside call graph of withContext launch won’t be cancelled (they are non-cancellable by defaultThis is incorrect
Antanas A.
03/21/2019, 9:24 AMgildor
03/21/2019, 9:24 AMAntanas A.
03/21/2019, 9:25 AMgildor
03/21/2019, 9:27 AMa Job which was started by withContext is not cancelled by thatwithContext doesn’t start any Jobs, I don’t understand what you mean
Antanas A.
03/21/2019, 9:29 AMgildor
03/21/2019, 9:34 AMAntanas A.
03/21/2019, 9:36 AMgildor
03/21/2019, 9:37 AMAntanas A.
03/21/2019, 9:37 AMgildor
03/21/2019, 9:37 AMAntanas A.
03/21/2019, 9:38 AMgildor
03/21/2019, 9:38 AMAntanas A.
03/21/2019, 9:38 AMgildor
03/21/2019, 9:40 AMAntanas A.
03/21/2019, 9:40 AMgildor
03/21/2019, 9:40 AMimplementing coroutineContext of CoroutineScope without explicit job is unknown behaviourWhat do you mean?
Antanas A.
03/21/2019, 9:41 AMgildor
03/21/2019, 9:42 AMAntanas A.
03/21/2019, 9:42 AMgildor
03/21/2019, 9:42 AMAntanas A.
03/21/2019, 9:42 AMgildor
03/21/2019, 9:42 AMAntanas A.
03/21/2019, 9:43 AMgildor
03/21/2019, 9:45 AMwithContext(this.coroutineScope)
Antanas A.
03/21/2019, 9:45 AMgildor
03/21/2019, 9:46 AMwithContext(MyDispatcher)
Antanas A.
03/21/2019, 9:47 AMgildor
03/21/2019, 9:48 AMAntanas A.
03/21/2019, 9:48 AMgildor
03/21/2019, 9:49 AMAntanas A.
03/21/2019, 9:49 AMgildor
03/21/2019, 9:49 AMAntanas A.
03/21/2019, 9:49 AMgildor
03/21/2019, 9:49 AMAntanas A.
03/21/2019, 9:50 AMgildor
03/21/2019, 9:51 AMAntanas A.
03/21/2019, 9:51 AMgildor
03/21/2019, 9:52 AMbut the pratice is if you are implementing CoroutineScope interface you should define job object otherwise it won’t be possible to control scopeDepending on how you do this
CoroutineScope()
or MainScope
builders job will be created for your, no need to create it explictlyAntanas A.
03/21/2019, 9:52 AMgildor
03/21/2019, 9:53 AMAntanas A.
03/21/2019, 9:53 AMgildor
03/21/2019, 9:53 AMAntanas A.
03/21/2019, 9:53 AMgildor
03/21/2019, 9:53 AMwithContext(this.coroutineContext)
just wrong by definition IMOAntanas A.
03/21/2019, 9:54 AMgildor
03/21/2019, 9:54 AMAntanas A.
03/21/2019, 9:54 AMgildor
03/21/2019, 9:54 AMAntanas A.
03/21/2019, 9:55 AMgildor
03/21/2019, 9:55 AMwithContext(this.coroutineContext) {
someSuspendCall()
}
and
someSuspendCall()
Is just the sameAntanas A.
03/21/2019, 9:55 AMgildor
03/21/2019, 9:56 AMcoroutineScope{}
instead of withContext(this.coroutineContext
Antanas A.
03/21/2019, 9:56 AMgildor
03/21/2019, 9:56 AMAntanas A.
03/21/2019, 9:56 AMgildor
03/21/2019, 9:56 AMAntanas A.
03/21/2019, 9:56 AMgildor
03/21/2019, 9:57 AMAntanas A.
03/21/2019, 9:57 AMgildor
03/21/2019, 9:57 AMAntanas A.
03/21/2019, 9:57 AMgildor
03/21/2019, 9:57 AMAntanas A.
03/21/2019, 9:57 AMgildor
03/21/2019, 9:58 AMAntanas A.
03/21/2019, 9:58 AMgildor
03/21/2019, 9:58 AMthis.coroutineContext[CoroutineDispather]
Antanas A.
03/21/2019, 9:58 AMgildor
03/21/2019, 9:58 AMAntanas A.
03/21/2019, 9:59 AMgildor
03/21/2019, 9:59 AMbut also I want somehow to cancel all suspended download() calls in system with another background operation which destroys and cancels downloaderI belive this is use case for Actor
Antanas A.
03/21/2019, 9:59 AMgildor
03/21/2019, 10:01 AMAntanas A.
03/21/2019, 10:01 AMgildor
03/21/2019, 10:01 AMAntanas A.
03/21/2019, 10:01 AMgildor
03/21/2019, 10:02 AMAntanas A.
03/21/2019, 10:02 AMgildor
03/21/2019, 10:05 AMAntanas A.
03/21/2019, 10:05 AMgildor
03/21/2019, 10:06 AMAntanas A.
03/21/2019, 10:06 AMgildor
03/21/2019, 10:07 AMAntanas A.
03/21/2019, 10:07 AMgildor
03/21/2019, 10:08 AMAntanas A.
03/21/2019, 10:08 AMgildor
03/21/2019, 10:09 AMAntanas A.
03/21/2019, 10:09 AMDico
03/21/2019, 1:19 PMwithScope
functionAntanas A.
03/21/2019, 2:00 PMDico
03/21/2019, 2:02 PMAntanas A.
03/21/2019, 2:03 PMDico
03/21/2019, 2:03 PMAntanas A.
03/21/2019, 2:04 PMgildor
03/21/2019, 2:04 PMAntanas A.
03/21/2019, 2:04 PM