quver
03/19/2019, 8:34 PMJob was added to the coroutineContext
override val coroutineContext: CoroutineContext
get() = Dispatchers.Main + job ?streetsofboston
03/19/2019, 8:40 PMJob and cancel it when necessaryquver
03/19/2019, 8:44 PMlaunch or async it will attach to the scope so then I will write
override fun onDestroy() {
super.onDestroy()
coroutineContext.cancelChildren()
}streetsofboston
03/19/2019, 8:45 PMjob will be a SupervisorJob. In the ViewModels’ onClear, you’d call the cancel method on that private val job = SupervisorJob()streetsofboston
03/19/2019, 8:48 PMabstract class CoBaseViewModel(context: CoroutineContext) : ViewModel(), CoroutineScope {
override val coroutineContext: CoroutineContext = SupervisorJob() + context
override fun onCleared() {
coroutineContext.cancel()
}
}streetsofboston
03/19/2019, 8:49 PMcontext is usually just the Dispatchers.Main)quver
03/19/2019, 8:54 PM+job we can specify in which Job will be linked launch or async?streetsofboston
03/19/2019, 8:56 PMjob from that point onquver
03/19/2019, 9:00 PMJob() by default, right?streetsofboston
03/19/2019, 9:04 PMquver
03/19/2019, 9:05 PMquver
03/19/2019, 9:09 PMprivate val job = Job()
override val coroutineContext: CoroutineContext
get() = Dispatchers.Main + jobstreetsofboston
03/19/2019, 9:10 PMjob. It’s a pattern 🙂quver
03/19/2019, 9:23 PMSupervisorJob to avoid stop parent coroutines by children crash.
but why we need a job above. we stop all jobs by coroutineContext.cancelChildren() and if we want pause some specific job we save it instance from launch and then stop it.
but what is best practise for this parent job?streetsofboston
03/19/2019, 9:29 PMcancelChildren suffices. But if your coroutine-scope and its context participates in structured concurrency, the calling context may need all its children to finish before it continues of finishes. That would mean cancelChildren is not enough, you’d need to call cancel to cancel your top-job.quver
03/19/2019, 9:32 PMstreetsofboston
03/19/2019, 9:33 PMstreetsofboston
03/19/2019, 9:34 PMstreetsofboston
03/19/2019, 9:34 PMquver
03/19/2019, 9:36 PMquver
03/19/2019, 10:22 PM+job there isn't default job. and by coroutineContext.cancelChildren() there isn't crash because of ?. but also there isn't cancelation.gildor
03/20/2019, 12:53 AMget() = Dispatchers.Main + jobInstead of this idiom you also can consider ready to user
MainScope()
class CoBaseViewModel : ViewModel(), CoroutineScope by MainScope()
it uses SupervisorJob by default and Main thread dispatcher
One more thing: keeping reference on job or use coroutineContext to cancel job is not necessary, there is CoroutineScope.cancel() extension function, so for ViewModel you can just do this:
override fun onCleared() {
super.onCleared()
cancel()
}gildor
03/20/2019, 1:14 AMwe stop all jobs byWhat is your use case for this? Fragments? Because for ViewModel it looks wrong, less error-prone to cancel Job, so if you have some async bug and will try to start coroutine after cancellation, this coroutine will be cancelled immediately, but withcoroutineContext.cancelChildren()
coroutineContext() you will get leaked coroutine insteadstreetsofboston
03/20/2019, 1:20 AMgildor
03/20/2019, 1:25 AMgildor
03/20/2019, 1:26 AMclass CoBaseViewModel(context: CoroutineContext) : ViewModel(), CoroutineScope by MainScope() + contextgildor
03/20/2019, 1:26 AMclass CoBaseViewModel(scope: CoroutineScope) : ViewModel(), CoroutineScope by scopequver
03/20/2019, 9:03 AMgildor
03/20/2019, 9:03 AMgildor
03/20/2019, 9:03 AMgildor
03/20/2019, 9:03 AMgildor
03/20/2019, 9:03 AMquver
03/20/2019, 9:04 AMgildor
03/20/2019, 9:04 AMgildor
03/20/2019, 9:05 AMgildor
03/20/2019, 9:05 AMgildor
03/20/2019, 9:06 AMquver
03/20/2019, 9:07 AMMainScope(): CoroutineScope = ContextScope(SupervisorJob() + Dispatchers.Main)
and in my example was
private val job = SupervisorJob()
override val coroutineContext: CoroutineContext
get() = Dispatchers.Main + jobgildor
03/20/2019, 9:14 AMgildor
03/20/2019, 9:15 AMstreetsofboston
03/20/2019, 9:51 AMgildor
03/20/2019, 9:54 AMgildor
03/20/2019, 9:54 AM