androidkotlinkotlin-coroutinesglobal-scope

Kotlin Coroutine GlobalScope documentation clarity


I'm having a hard time understanding the usages and documentation for GlobalScope. The docs states:

A global CoroutineScope not bound to any job.

Global scope is used to launch top-level coroutines which are operating on the whole application lifetime and are not cancelled prematurely. Another use of the global scope is operators running in Dispatchers.Unconfined, which don’t have any job associated with them.

Application code usually should use an application-defined CoroutineScope. Using async or launch on the instance of GlobalScope is highly discouraged.

  1. What does it mean when GlobalScope is not bound to any job? Because I can do

    val job = GlobalScope.launch {
        // some work
    }
    job.cancel() 
    
  2. It says they are not canceled prematurely. What does this mean? As you can see above I can cancel it.

  3. Lastly it says, it operates on the whole application lifetime. So the scope stays alive until the application dies. How does this compare with CoroutineScope? When I exit an Android Activity in the middle of a running CoroutineScope, it'll still be alive and runs until completion. Does it just mean the CoroutineScope will get cleaned up w/ garbage collection after it completes and GlobalScope wont?

link to docs: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-global-scope/


Solution

    1. What does it mean when GlobalScope is not bound to any job? Because I can do...

    This refers to the lack of Job object associated to the CoroutineScope, not individual coroutine Jobs within the "Scope".

    1. It says they are not canceled prematurely. What does this mean? As you can see above I can cancel it.

    Calling GlobalScope.cancel() at any point will throw an IllegalArgumentException.

    so this would produce the same error :

    fun main(args: Array<String>) {
    
        val myScope : CoroutineScope = object : CoroutineScope {
            override val coroutineContext: CoroutineContext = Dispatchers.IO // no job added i.e + SupervisorJob()
        }
    
    
        val job = myScope.launch { longRunningTask() }
    
        Thread.sleep(5_000)
        job.cancel() // this is fine - individual coroutine cancelled
        myScope.cancel() // this will throw an error, same as GlobalScope.cancel()
        
    }
    
    1. Lastly it says, it operates on the whole application lifetime. So the scope stays alive until the application dies. How does this compare with CoroutineScope? When I exit an Android Activity in the middle of a running CoroutineScope, it'll still be alive and runs until completion. Does it just mean the CoroutineScope will get cleaned up w/ garbage collection after it completes and GlobalScope wont?

    GlobalScope is an object class - a singleton, thus lasts as long as the process it runs in. GlobalScope implements CoroutineScope its just a predefined scope that comes with the library. Coroutines can be launched from GlobalScope but the caller must take care to retain the Job object and cancel each coroutine via the Job. When using custom CoroutineScope you can have greater control on what happens when you call the extension function CoroutineScope.cancel() - for instance cancelling all child coroutines "running" in that scope.

    I'm no authority on the subject but that's how I interpet the documentation and observed behaviours of the library.

    If I'm honest I think most people struggle to explain coroutines simply and concisely - most articles on the subject are not easy reading and usually I come away more confused. Having delved into the library source code a bit after it usually demistifies things somewhat, but you can also see it is still very much in a state of continuing development.