https://kotlinlang.org logo
Join the conversationJoin Slack
Channels
100daysofcode
100daysofkotlin
100daysofkotlin-2021
advent-of-code
aem
ai
alexa
algeria
algolialibraries
amsterdam
android
android-architecture
android-databinding
android-studio
androidgithubprojects
androidthings
androidx
androidx-xprocessing
anime
anko
announcements
apollo-kotlin
appintro
arabic
argentina
arkenv
arksemdevteam
armenia
arrow
arrow-contributors
arrow-meta
ass
atlanta
atm17
atrium
austin
australia
austria
awesome-kotlin
ballast
bangladesh
barcelona
bayarea
bazel
beepiz-libraries
belgium
berlin
big-data
books
boston
brazil
brikk
budapest
build
build-tools
bulgaria
bydgoszcz
cambodia
canada
carrat
carrat-dev
carrat-feed
chicago
chile
china
chucker
cincinnati-user-group
cli
clikt
cloudfoundry
cn
cobalt
code-coverage
codeforces
codemash-precompiler
codereview
codingame
codingconventions
coimbatore
collaborations
colombia
colorado
communities
competitive-programming
competitivecoding
compiler
compose
compose-android
compose-desktop
compose-hiring
compose-ios
compose-mp
compose-ui-showcase
compose-wear
compose-web
connect-audit-events
corda
cork
coroutines
couchbase
coursera
croatia
cryptography
cscenter-course-2016
cucumber-bdd
cyprus
czech
dagger
data2viz
databinding
datascience
dckotlin
debugging
decompose
decouple
denmark
deprecated
detekt
detekt-hint
dev-core
dfw
docs-revamped
dokka
domain-driven-design
doodle
dsl
dublin
dutch
eap
eclipse
ecuador
edinburgh
education
effective-kotlin
effectivekotlin
emacs
embedded-kotlin
estatik
event21-community-content
events
exposed
failgood
fb-internal-demo
feed
firebase
flow
fluid-libraries
forkhandles
forum
fosdem
fp-in-kotlin
framework-elide
freenode
french
fritz2
fuchsia
functional
funktionale
gamedev
ge-kotlin
general-advice
georgia
geospatial
german-lang
getting-started
github-workflows-kt
glance
godot-kotlin
google-io
gradle
graphic
graphkool
graphql
graphql-kotlin
graviton-browser
greece
grpc
gsoc
gui
hackathons
hacktoberfest
hamburg
hamkrest
helios
helsinki
hexagon
hibernate
hikari-cp
hire-me
hiring
hongkong
hoplite
http4k
hungary
hyderabad
image-processing
india
indonesia
inkremental
intellij
intellij-plugins
intellij-tricks
internships
introduce-yourself
io
ios
iran
israel
istanbulcoders
italian
jackson-kotlin
jadx
japanese
jasync-sql
java-to-kotlin-refactoring
javadevelopers
javafx
javalin
javascript
jdbi
jhipster-kotlin
jobsworldwide
jpa
jshdq
juul-libraries
jvm-ir-backend-feedback
jxadapter
k2-early-adopters
kaal
kafka
kakao
kalasim
kapt
karachi
karg
karlsruhe
kash_shell
kaskade
kbuild
kdbc
kgen-doc-tools
kgraphql
kinta
klaxon
klock
kloudformation
kmdc
kmm-español
kmongo
knbt
knote
koalaql
koans
kobalt
kobweb
kodein
kodex
kohesive
koin
koin-dev
komapper
kondor-json
kong
kontent
kontributors
korau
korean
korge
korim
korio
korlibs
korte
kotest
kotest-contributors
kotless
kotlick
kotlin-asia
kotlin-beam
kotlin-by-example
kotlin-csv
kotlin-data-storage
kotlin-foundation
kotlin-fuel
kotlin-in-action
kotlin-inject
kotlin-latam
kotlin-logging
kotlin-multiplatform-contest
kotlin-mumbai
kotlin-native
kotlin-pakistan
kotlin-plugin
kotlin-pune
kotlin-roadmap
kotlin-samples
kotlin-sap
kotlin-serbia
kotlin-spark
kotlin-szeged
kotlin-website
kotlinacademy
kotlinbot
kotlinconf
kotlindl
kotlinforbeginners
kotlingforbeginners
kotlinlondon
kotlinmad
kotlinprogrammers
kotlinsu
kotlintest
kotlintest-devs
kotlintlv
kotlinultimatechallenge
kotlinx-datetime
kotlinx-files
kotlinx-html
kotrix
kotson
kovenant
kprompt
kraph
krawler
kroto-plus
ksp
ktcc
ktfmt
ktlint
ktor
ktp
kubed
kug-leads
kug-torino
kvision
kweb
lambdaworld_cadiz
lanark
language-evolution
language-proposals
latvia
leakcanary
leedskotlinusergroup
lets-have-fun
libgdx
libkgd
library-development
linkeddata
lithuania
london
losangeles
lottie
love
lychee
macedonia
machinelearningbawas
madrid
malaysia
mathematics
meetkotlin
memes
meta
metro-detroit
mexico
miami
micronaut
minnesota
minutest
mirror
mockk
moko
moldova
monsterpuzzle
montreal
moonbean
morocco
motionlayout
mpapt
mu
multiplatform
mumbai
munich
mvikotlin
mvrx
myndocs-oauth2-server
naming
navigation-architecture-component
nepal
new-mexico
new-zealand
newname
nigeria
nodejs
norway
npm-publish
nyc
oceania
ohio-kotlin-users
oldenburg
oolong
opensource
orbit-mvi
osgi
otpisani
package-search
pakistan
panamá
pattern-matching
pbandk
pdx
peru
philippines
phoenix
pinoy
pocketgitclient
polish
popkorn
portugal
practical-functional-programming
proguard
prozis-android-backup
pyhsikal
python
python-contributors
quasar
random
re
react
reaktive
realm
realworldkotlin
reductor
reduks
redux
redux-kotlin
refactoring-to-kotlin
reflect
refreshversions
reports
result
rethink
revolver
rhein-main
rocksdb
romania
room
rpi-pico
rsocket
russian
russian_feed
russian-kotlinasfirst
rx
rxjava
san-diego
science
scotland
scrcast
scrimage
script
scripting
seattle
serialization
server
sg-user-group
singapore
skia-wasm-interop-temp
skrape-it
slovak
snake
sofl-user-group
southafrica
spacemacs
spain
spanish
speaking
spek
spin
splitties
spotify-mobius
spring
spring-security
squarelibraries
stackoverflow
stacks
stayhungrystayfoolish
stdlib
stlouis
strife-discord-lib
strikt
students
stuttgart
sudan
swagger-gradle-codegen
swarm
sweden
swing
swiss-user-group
switzerland
talking-kotlin
tallinn
tampa
teamcity
tegal
tempe
tensorflow
terminal
test
testing
testtestest
texas
tgbotapi
thailand
tornadofx
touchlab-tools
training
tricity-kotlin-user-group
trójmiasto
truth
tunisia
turkey
turkiye
twitter-feed
uae
udacityindia
uk
ukrainian
uniflow
unkonf
uruguay
utah
uuid
vancouver
vankotlin
vertx
videos
vienna
vietnam
vim
vkug
vuejs
web-mpp
webassembly
webrtc
wimix_sentry
wwdc
zircon
Powered by Linen
coroutines
  • m

    Marcelo Hernandez

    05/18/2019, 8:55 PM
    Been looking at the new test helpers such as
    runBlockingTest
    ,
    TestCoroutineDispatcher
    ,
    TestCoroutineScope
    , etc. They look promising, however I haven't been able to figure out a way to stub a dependency's
    suspend
    function using
    mockito-kotlin
    such that it suspends indefinitely. The goal is to test scenarios within my Android
    ViewModel
    where
    onCleared()
    is called before a
    suspend
    function returns a result. Basically something like:
    private fun givenStatusNeverReceived() = runBlocking {
        // loadStatus() is a suspend function
        given(repository.loadStatus()).willAnswer {
            // suspend indefinitely
        }
    }
    l
    • 2
    • 5
  • e

    efemoney

    05/19/2019, 7:39 PM
    How do I attach a piece of code to run when a
    Flow
    is cancelled/disposed. Something like
    ObservableEmitter.setCancellable { ... }
    in the rx world. I want to use
    Flow
    to model an add/remove listener so that a listener is attached when the flow is “subscribed” to and detached when the subscription is “disposed”. Forgive the rx lingo, pretty new to
    Flow
    so I will also appreciate reading material that can tie or at least differenciate between my RxJava knowlege and
    Flow
    :thread-please: 1
    o
    t
    e
    • 4
    • 8
  • r

    ribesg

    05/20/2019, 10:29 AM
    I’m trying to run some Android tests, what did I miss? I have
    kotlinx-coroutines-test
    in my test dependencies.
    java.lang.NullPointerException
    	at kotlinx.coroutines.CoroutineContextKt.newCoroutineContext(CoroutineContext.kt:57)
    	at kotlinx.coroutines.BuildersKt__Builders_commonKt.launch(Builders.common.kt:50)
    	at kotlinx.coroutines.BuildersKt.launch(Unknown Source)
    	at kotlinx.coroutines.BuildersKt__Builders_commonKt.launch$default(Builders.common.kt:47)
    	at kotlinx.coroutines.BuildersKt.launch$default(Unknown Source)
    • 1
    • 2
  • k

    kupris

    05/20/2019, 12:28 PM
    Hello, I would like to use coroutines to handle delay and update of text from an EditText via his TextWatcher listener. In fact, if user continue to type something, I would like to cancel current coroutine and fire another one. It would works like timer/handler implementation for this type of case. Thanks in advance for your time and sorry for my crappy english 😅
    g
    • 2
    • 16
  • i

    ilya-gh

    05/20/2019, 12:49 PM
    Hey guys, I am trying to mock
    delay
    in the following code:
    class A(val coroutineContext: CoroutineContext = EmptyCoroutineContext) {
        fun work(): String {
            val result = runBlocking(coroutineContext) {
                delay(3000)
                return "some_result"
            }
            return result
        }
    }
    
    @Test
    fun `tests work`() {
        val result = A().work()
    
        assertEquals("some_result", result)
    }
    If a pass
    TestCoroutineContext()
    to runBlocking the
    delay
    is ignored as expected. However, It’s deprecated in favor of TestCoroutineScope. TestCoroutineScope. However If I pass TestCoroutineScope the test never finishes:
    @Test
    fun `tests work`() {
        val result = A(TestCoroutineScope(TestCoroutineDispatcher()).coroutineContext).work()
        
        // never reaches here
        assertEquals("some_result", result)
    }
    What I am missing?
    g
    • 2
    • 2
  • a

    Alexjok

    05/20/2019, 1:11 PM
    Hello, how i can create Kotlin job and start it later?
    m
    g
    • 3
    • 11
  • w

    Wilson Castiblanco

    05/20/2019, 5:50 PM
    Hello guys! is there another way to return a value from a Coroutine without blocking the Main Thread? Maybe using Channels or Flow? . I'm getting an object from Room and I want to return a specific attribute from that object after get it.
    😒uspend: 3
    s
    • 2
    • 6
  • o

    Oleh Havrysh

    05/21/2019, 9:39 AM
    Hi! I want to wrap my player callback into suspend function that will just suspend until something completed without returning any value. Is there some alternative for
    suspendCoroutine
    that doesn’t require passing result value?
    -.kt
    g
    m
    • 3
    • 8
  • m

    Marko Mitic

    05/21/2019, 11:28 AM
    Hi everyone, I'm starting to use coroutines in prod and could use a bit of advice. I need to observe state of couple of components, both should offer subscribe/unsubscribe ops. I'm thinking of having a channel for each, created on subscription, canceling does the unsubscribe, and observe both using
    select
    . Is that fine? Are there any channel constructs that could help?
    g
    • 2
    • 12
  • l

    louiscad

    05/21/2019, 1:51 PM
    I find
    Flow
    very well designed, kudos to the people involved. I like how it reuses the continuation of the consumer and how exceptions and cancellation are propagated. Is it bad to use them in production under their preview status? :yes: or 🇳🇴
    🇳🇴 2
    👏 7
    💯 5
    e
    l
    • 3
    • 11
  • s

    sam

    05/22/2019, 7:06 PM
    If I am writing a function that can call suspendable functions, is there a preference between making that function suspend itself, or defining it on CoroutineScope ? Or in other words, when should one use suspend and when should one use CoroutineScope as a receiver ?
    😒uspend: 1
    e
    • 2
    • 1
  • b

    Bob Glamm

    05/22/2019, 7:18 PM
    Does
    launch
    require a corresponding
    join
    or will the coroutine resources created with
    launch
    be automatically reclaimed on coroutine completion?
    e
    • 2
    • 2
  • t

    tseisel

    05/22/2019, 9:03 PM
    Does
    Flow
    have a corresponding
    select
    clause, and if it doesn't, is it planned ?
    o
    g
    • 3
    • 5
  • a

    Antanas A.

    05/24/2019, 8:08 AM
    Is there are any debug facilities for that? e.g. configuring that channels will throw exception after n minutes of suspension
    d
    • 2
    • 3
  • a

    Antanas A.

    05/24/2019, 12:45 PM
    I hope someday channels will be bound to coroutine lifecycles and we no longer need explicitly do coroutineContext[Job]!!.invokeOnCompletion { broadcastChannel.close() }
    g
    l
    m
    • 4
    • 17
  • g

    gotoOla

    05/24/2019, 3:10 PM
    Hi! Does anyone have any pointer in how you could debug a coroutine that doesn’t seem to wake up at the correct time? I have a test where a message is picked up on a queue which results in a request towards a stub (which returns 404). The problem is that even though the stub is up and ready it seems that the coroutine that is suspending (it’s a post from the ktor http client) is not “woken up” until after about 30 seconds when the same message gets republished on the queue. The coroutine that I suspect to not be woken up correctly is surrounded in a repeat, I see that first repeat happen but then it just goes silent
    g
    • 2
    • 7
  • m

    Matej Drobnič

    05/25/2019, 7:57 AM
    Is there a reason to NOT use
    MainDispatcher.immediate
    over just regular
    MainDispatcher
    ?
    l
    e
    p
    • 4
    • 13
  • w

    Winowiczlukasz

    05/26/2019, 6:50 PM
    How change Entity class to Protected? I have message Modifier protected is not applicable inside "file".
    l
    • 2
    • 1
  • d

    Dico

    05/27/2019, 3:43 AM
    Under what circumstances would
    delay
    suspend forever, if I pass it a value around 500-1500 MS? I have some code that is looping with an interval which works perfectly in one environment but not in another - where it's used as a plugin in some other software. The dispatcher used is a single thread dispatcher created using
    Executors.newSingleThreadDispatcher(threadFactory).asCoroutineDispatcher()
    The behavior I'm seeing is that it never resumes the coroutine.
    g
    • 2
    • 12
  • t

    Tuan Kiet

    05/28/2019, 2:08 AM
    Why does flow stream emit a serial of items instead of only the latest one (like observable in rx) when collect (subscribe), Is there any way to work around this behaviour?
    g
    • 2
    • 99
  • s

    Steven

    05/28/2019, 2:43 PM
    I also have a problem with the delay function. I am trying to do a simple while in kotlin multiplatform. The following function works in android but not on iOS. In the logs on iOS side, i see "Before delay" but i don't see the other print.
    -.txt
    d
    v
    g
    • 4
    • 6
  • m

    Mark

    05/29/2019, 6:31 AM
    I’m writing a suspend function that takes a suspend block as an arg, executes it asynchronously, meanwhile monitoring the length of a file and periodically notifying a callback of the current file length. At the moment I have this, but I’m sure there’s a much neater way, for example, not using GlobalScope.
    suspend fun File.trackLength(fileLengthCallback: (Long) -> Unit, refreshInterval: Long = 100L, block: suspend () -> Unit) {
        val deferred = GlobalScope.async {
            block()
        }
        while (deferred.isActive) {
            fileLengthCallback(length())
            delay(refreshInterval)
        }
        fileLengthCallback(length())
    }
    g
    l
    +2
    • 5
    • 69
  • j

    Jacques Smuts

    05/29/2019, 9:12 AM
    I have a situation where I use coroutines and the upcoming semaphore class for coroutines will be very useful. However I’m pretty sure I will shoot myself in the foot and create a deadlock. Can anyone recommend a good book for understanding and handling these types of threading scenarios and preventing and resolving deadlock and the like?
    s
    z
    • 3
    • 7
  • e

    efemoney

    05/29/2019, 10:24 AM
    Whats the difference b/w
    coroutineScope
    and
    launch
    ? (Its not super clear from the docs)
    g
    t
    • 3
    • 44
  • m

    Mark

    05/29/2019, 12:11 PM
    Suppose I have
    suspend fun myFun() {
        repeat(100) {
            someSuspendingFunSpecifyingIODispatcher()
            someQuickNonSuspendingFun()
        }
    }
    At the top-level of myFun() is it better to have withContext(Dispatchers.IO), coroutineScope {} or leave it as it is?
    g
    p
    • 3
    • 30
  • d

    Dan Johansson

    05/29/2019, 3:54 PM
    Hi there, I'm in the middle of learning to use coroutines and I'm having difficulties grasping why my test is passing. The test passes while the console prints out the exception stack trace. If I use
    async
    (and
    .await
    in my test) it fails as expected but I want to use
    launch
    (actual function is in my Android ViewModel) and I am kinda lost. A workaround is to check whether the job
    isCancelled
    , which works but is a bit clunky (I guess it's possible to create some test rule..). I've read the docs but haven't come up with anything. Maybe I'm going about this the wrong way and there's a better approach? Any pointer or direction is very much appreciated.
    // in ViewModel
    val job = Job()
    val viewModelScope = CoroutineScope(Dispatchers.Main + job)
    
    fun someFunction() = viewModelScope.launch {
      throw IllegalStateException("reasons")
    }
    
    ...
    
    @Test
    fun `should fail`() = runBlocking {
      // prints error but the test passes
      someFunction().join()
    }
    
    @Test
    fun `successfully failing workaround`() = runBlocking {
      // this feels wrong
      val job = someFunction()
      someFunction.join()
      assertFalse(job.isCancelled)
    }
    g
    • 2
    • 25
  • r

    rook

    05/30/2019, 7:43 PM
    Is it possible to use channels to wait for a signal to do work? Something like:
    suspend fun waitForUpdates(): ReceiveChannel<Update> = produce {
      onUpdateHook { update ->
        send(update)
      }
    }
    
    fun startWaitingForUpdates() {
      launch {
        waitForUpdates().onReceive { update ->
          doUpdate(update)
        }
      }
    }
    s
    d
    b
    • 4
    • 13
  • c

    coder82

    05/31/2019, 8:07 AM
    How could I check if a singlethreaded coroutine context is currently executing or not?
    g
    • 2
    • 13
  • c

    coder82

    05/31/2019, 9:06 AM
    When I use withContext(...){}, how go I get the Job?
    g
    • 2
    • 1
  • t

    Tuan Kiet

    06/02/2019, 8:47 AM
    anyone know how to get coroutine context from a suspend function? in order to launch a job within a suspend function, we need to switch context with
    withContext
    to get
    this
    as a coroutine context?
    t
    s
    +2
    • 5
    • 59
Powered by Linen
Title
t

Tuan Kiet

06/02/2019, 8:47 AM
anyone know how to get coroutine context from a suspend function? in order to launch a job within a suspend function, we need to switch context with
withContext
to get
this
as a coroutine context?
t

tseisel

06/02/2019, 8:53 AM
To launch a new job, you need a
CoroutineScope
, not a
CoroutineContext
. The best way to obtain the CoroutineScope of a coroutine is to pass it as argument to the function that needs it.
👎 1
Also. There is a convention for defining functions that starts coroutines :
fun CoroutineScope.launchMyJob(...)
Functions defined like this does not suspend until the job is completed, as opposed to
suspend fun
.
s

simon.vergauwen

06/02/2019, 8:54 AM
There is
coroutineContext
as a property available within any
suspend
function or lambda.
👍 2
t

Tuan Kiet

06/02/2019, 9:00 AM
@simon.vergauwen that is a function
and not sure which is less overhead
suspendCoroutineUninterceptedOrReturn
or
withContext
s

simon.vergauwen

06/02/2019, 9:02 AM
I don't think
suspendCoroutineOrReturn
is what you're looking for. It's rather low level.
Do you just want to launch and forget? Or do you depend on the result?
t

Tuan Kiet

06/02/2019, 9:25 AM
that is coroutineContext() implemetation
again which is less expensive coroutineContext() or withContext() ?
g

gildor

06/02/2019, 9:49 AM
coroutineContext is not a function, this is a property
What is your use case? From your first message is completely not clear what you want to achieve, if you just want to use launch/async from suspend function use coroutineScope{} or supervisorScope{} functions which create scopes and suspend until child coroutineScope active, but you asking about coroutine context which cannot be used to start launch/async coroutines
withContext also works for this, but it make sense to use only if you really want to change context, otherwise just use coroutineScope/supervisorScope
t

Tuan Kiet

06/02/2019, 9:56 AM
wrong typing though, I mean
coroutineScope
pretty sure within a suspend function coroutineScope is a function
public suspend fun <R> coroutineScope(block: suspend CoroutineScope.() -> R): R
g

gildor

06/02/2019, 9:57 AM
coroutineScope is a function of course, coroutineContext is a property (and actually intrinsic)
t

Tuan Kiet

06/02/2019, 9:57 AM
oh
so.. same question again, not what I should use, which is less overhead
coroutineScope{}
or
withContext{}
?
g

gildor

06/02/2019, 9:59 AM
they are very similar, but if you don't want to switch context, only create a new scope, just use coroutineScope, not because of performance, bit just semantically
t

Tuan Kiet

06/02/2019, 10:01 AM
so.. the suspend function does not have scope?
g

gildor

06/02/2019, 10:02 AM
Probably coroutineScope a bit more performant just because less context objects will be created, but actually not sure, because coroutineScope also create own context, so I think it's the same, but use withContext just to create scope is just strange and confusing
Sure, there is no scope in suspend function and it's not needed for most of cases
t

Tuan Kiet

06/02/2019, 10:05 AM
apparently I need a function which will return a Job, which lead me to this, not sure it’s the best way?
suspend fun sdfsdf(): Job {
    return coroutineScope {
        launch { 
            
        }
    }
}
g

gildor

06/02/2019, 10:05 AM
Oh, no, it doesn't make sense and will not work
t

Tuan Kiet

06/02/2019, 10:06 AM
why?
g

gildor

06/02/2019, 10:06 AM
Job will be always closed in this case, because coroutineScope will not return until launch is finished, this is whole point of this function
t

Tuan Kiet

06/02/2019, 10:07 AM
so what should I do?
g

gildor

06/02/2019, 10:07 AM
Could you please give your use case. Suspend function that returns Job is not a use case
t

Tuan Kiet

06/02/2019, 10:08 AM
my previous function does return a Job but that Job is already finish, am I correct?
g

gildor

06/02/2019, 10:08 AM
Yes
t

Tuan Kiet

06/02/2019, 10:08 AM
lol
g

gildor

06/02/2019, 10:09 AM
Do you want to use this job to cancel invocation of suspend function body?
t

Tuan Kiet

06/02/2019, 10:12 AM
override suspend fun doWork(): Result = coroutineScope {
        workJob = launch {
            doActualWork()
        }
        workJob?.invokeOnCompletion {
            if (it != null) {
                showStoppedNotification()
            }
        }
        Result.success()
    }

    private suspend fun doActualWork() {
        // stuff
    }
doWork is a framework method
g

gildor

06/02/2019, 10:14 AM
If my assumption is correct, than no need to return Job from suspend function for this, just wrap to launch (or any other builder) on call site to control lifecycle, it's common idiom in coroutines, instead of putting launch inside, wrap it on call site, it make it universal (call site controls lifecycle) and safe to use (no way to leak it):
suspend fun sdfsdf() {}

// On call site
val job = launch { sdfsdf() }
//Launch invocation in background and also may be cancelled
job.cancel()
t

Tuan Kiet

06/02/2019, 10:15 AM
and this can be cancel any time (by the framework) so I need a job instance to clean up stuff after it got canceled
and I don’t want to put everything I launch{} so I made a function for it
g

gildor

06/02/2019, 10:16 AM
To handle cancellation just wrap suspend function to try/catch/finally
t

Tuan Kiet

06/02/2019, 10:17 AM
doWork is called by the framework
g

gildor

06/02/2019, 10:17 AM
In finally you can clean resources
So?
This is just suspend function, use try catch to handle cancellation
t

Tuan Kiet

06/02/2019, 10:17 AM
do you mean I need to try catch in doActualWork?
or in doWork?
g

gildor

06/02/2019, 10:19 AM
anywhere, depends on where resource is acquired
If you want to keep current semantics, than in doWork
t

Tuan Kiet

06/02/2019, 10:21 AM
I thought when suspend function got canceled, it will stop immediately, no change to reach catch or final
g

gildor

06/02/2019, 10:21 AM
override suspend fun doWork(): Result {
        try {
            doActualWork()
        } catch (e: CancellationException) {
            // You can handle cancellation separately, if you want
       } catch (e: Exception) {
            showStoppedNotification()
           //Should we return Result.fail()?
       }
       return Result.success()
    }

    private suspend fun doActualWork() {
        // stuff
    }
when coroutine where suspend function should be invoked is cancelled, suspend function will throw cancellation exception and this exception propagated to parent suspend functions
t

Tuan Kiet

06/02/2019, 10:23 AM
note that
doWork
is called by that framework and canceled by the framework too, do we need doActualWork at all?
g

gildor

06/02/2019, 10:24 AM
but you should put
//stuff
somewhere, isn’t it? I mean nothing prevents you from inline it in doWork, like with any other function, I’m not sure what is your concern in this case
t

Tuan Kiet

06/02/2019, 10:25 AM
assume that I could do it in try{}, doWork got canceled, does the catch and final statement get called?
g

gildor

06/02/2019, 10:29 AM
Of course, otherwise it would break error handling and resource handling (your case), suspend function cancellation based on throwing CancellationException that then handled differently by coroutines runtime, but try/catch/finally contract is still work for suspend functions
t

Tuan Kiet

06/02/2019, 10:35 AM
thank for your support
I appreciate it
g

gildor

06/02/2019, 10:38 AM
You are welcome
d

Dico

06/02/2019, 11:22 AM
Yes they get called, keep in mind that errors other than cancellation might also cancel parent coroutines regardless of catching the error in code.
Am I right Andrey?
g

gildor

06/02/2019, 12:12 PM
No, suspend function exception do not scope by itself (I mean handled exception, unhandled will be propagated and may cause scope cancellation or crash, the same as any other exception) if suspend function throws, it will not cancel scope automatically, so it's fine to try/catch it with no scope cancellation
Behavior with scope cancellation (if one of child background coroutines throws) designed to avoid coroutine resources leaking. Without this, if you would run 2 parallel jobs in one scope and one of them failed, it wouldn't cause cancellation of second one, so it will continue invocation, but usually result is useless, because another part of result is failed
View count: 8