Kotlin

Kotlin

Made by DeepSource

Avoid using GlobalScope to launch coroutines KT-E1001

Bug risk
Major

The use of GlobalScope.launch or GlobalScope.async was detected. The use of GlobalScope is discouraged according to Kotlin' official documentation.

GlobalScope is marked with the @DelicateCoroutinesApi annotation, signifying that using it could cause problems such as resource or memory leaks if used incorrectly.

The Kotlin documentation states that the GlobalScope instance is used to launch top-level coroutines that operate on the whole application's lifetime.

Since such coroutines will operate over the lifetime of the entire program, they are not subject to the restrictions of any framework-specific state, such as that of DI components or Android view scopes.

If you use GlobalScope to launch an operation that should have been confined to a smaller lifetime, such as that of a request handler or a fragment, it is possible to allow a resource to stay in memory for longer than the lifetime of its originating scope. In other words, memory or resources will be leaked.

Bad Practice

fun foo() {
    GlobalScope.launch { delay(1_000L) }
}

Recommended

Remove usages of GlobalScope.launch and GlobalScope.async from your codebase.

There are various approaches you can take instead:

  1. If you are using non-coroutine code and want to start using coroutines, use runBlocking to create a local coroutine scope and keep all async operations within that runBlocking call.

    Note that runBlocking should be used sparingly, and you should only call it at the top of the coroutine hierarchy, and never within other coroutines.

  2. In frameworks like Spring, coroutine scope creation is handled for you already, and if you need to create new scopes, you just need to use coroutineScope to create a new local scope that will end when you finish handling a request, or whatever other operation you are performing.
  3. For Android, use viewModelScope if you are within a ViewModel, or lifecycleScope if you are within an activity/fragment.
fun foo() {
    // defined elsewhere
    localScope.launch { delay(1_000L) }
}

fun onDestroy() {
    localScope.cancel()
}

References