DEV Community

myougaTheAxo
myougaTheAxo

Posted on • Originally published at zenn.dev

Structured Concurrency in Kotlin - coroutineScope, Job & Cancellation

Structured Concurrency in Kotlin - coroutineScope, Job & Cancellation

Structured concurrency ensures all coroutines are properly tracked and cancelled. Master Job, coroutineScope, and cancellation.

Scoped Coroutines

coroutineScope creates a scope that waits for all children:

suspend fun fetchUserData(): UserData = coroutineScope {
    val userDeferred = async { fetchUser() }
    val postsDeferred = async { fetchPosts() }

    // Both requests run in parallel, but scope waits for both
    UserData(
        user = userDeferred.await(),
        posts = postsDeferred.await()
    )
}

// Exceptions in either async are propagated
Enter fullscreen mode Exit fullscreen mode

Job and Cancellation

val job = viewModelScope.launch {
    try {
        repeat(100) { i ->
            println("Working $i")
            delay(1000)
        }
    } catch (e: CancellationException) {
        println("Job cancelled")
        throw e // Re-throw to propagate
    } finally {
        println("Cleanup")
    }
}

// Cancel the job
job.cancel()
Enter fullscreen mode Exit fullscreen mode

SupervisorJob for Independent Children

val supervisor = SupervisorJob()
val scope = CoroutineScope(Dispatchers.Main + supervisor)

scope.launch {
    throw Exception("Child 1 failed")
}

scope.launch {
    delay(1000)
    println("Child 2 still runs") // Not affected by Child 1 failure
}
Enter fullscreen mode Exit fullscreen mode

Proper ViewModel Cleanup

class MyViewModel : ViewModel() {
    override fun onCleared() {
        viewModelScope.cancel()
    }
}
Enter fullscreen mode Exit fullscreen mode

Best Practices

  • Use viewModelScope for ViewModel coroutines
  • Catch CancellationException and re-throw
  • Use coroutineScope for parallel tasks
  • Use SupervisorJob for independent operations
  • Always provide proper finally cleanup

8 Android app templates on Gumroad

Top comments (0)