Shawn Witte
03/31/2021, 9:25 PMsuspend
function via Retrofit) that is part of my (Android app's ) data syncing. I am attempting to ensure that the code block with this call completes, even if the calling coroutine (started in a viewModelScope
) is cancelled. My initial thought was to wrap the function in appScope.async { //code }.await()
, where appScope
is an application-level scope. Android Studio has suggested that I just use withContext(appScope.coroutineContext) { //code }
.
Are these really equivalent in terms of coroutine lifecycles? I had thought that withContext
created a child coroutine (with a different, but related CoroutineContext
) that would be cancelled if the context creating it is cancelled, whereas appScope.async()
creates a whole new coroutine with its own lifecycle tied to appScope
and not the original context.
Also welcoming input on my solution to the initial problem.ursus
03/31/2021, 9:27 PMShawn Witte
03/31/2021, 9:55 PMsomeScope.launch {
appScope.async {
//code
}.await()
}
and
someScope.launch {
withContext(appScope.coroutineContext) {
//code
}
}
and I call someScope.cancel()
, then does the inner work receive the cancellation signal in either case? My instinct is that it will in the second case but not the first case because withContext
merges the contexts.ursus
03/31/2021, 10:03 PMShawn Witte
03/31/2021, 10:31 PM"did something1"
prints, but "did something2"
does not):
val appScope = CoroutineScope(Job() + Dispatchers.Default)
val tempScope = CoroutineScope(Job() + Dispatchers.Default)
runBlocking {
tempScope.launch {
val thing = appScope.async {
delay(1000)
println("did something1")
"thing1"
}.await()
println(" did $thing")
}
tempScope.launch {
val thing = withContext(appScope.coroutineContext) {
delay(1000)
println("did something2")
"thing2"
}
println(" did $thing")
}
tempScope.cancel()
delay(3000)
}
"did something2"
and " did thing2"
, but I think that's because weird timings. It seems more consistent with a delay
value of 2000
or more."did something1"
and "did something2"
after tempScope
was cancelled:
runBlocking {
val appScope = CoroutineScope(Job() + Dispatchers.Default)
val tempScope = CoroutineScope(Job() + Dispatchers.Default)
tempScope.launch {
val thing = appScope.async {
while (isActive) {
delay(100)
println("did something1")
}
}
println(" did ${thing.await()}")
}
tempScope.launch {
val thing = withContext(appScope.coroutineContext) {
while (isActive) {
delay(100)
println("did something2")
}
"thing2"
}
println(" did $thing")
}
tempScope.cancel()
delay(1000)
println("tempScope cancelled")
delay(1000)
appScope.cancel()
println("appScope cancelled")
}
natario1
04/01/2021, 7:58 AMstreetsofboston
04/01/2021, 6:44 PM