Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Cracking Kotlin Coroutines

Cracking Kotlin Coroutines

The presentation was held at Droidcon Italy 2022 and was accompanied with live coding with examples from this GitHub repo https://github.com/dahlbergbob/cracking-coroutines-droidcon-it

Bob Dahlberg

October 06, 2022
Tweet

More Decks by Bob Dahlberg

Other Decks in Programming

Transcript

  1. Cheating // clears the text field clear(optional:String = ””) //

    variants adds to the text field out(message:Any) // launches a coroutine viewModelScope.launch {}
  2. Suspension Suspension is one of the most central and fundamental

    part of Kotlin coroutines. Suspending is pausing Suspending is resuming Dividing the coroutine into smaller pieces
  3. Suspension fun order() { out(0) viewModelScope.launch { out(1) launch {

    out(2) delay(100) out(3) } launch { out(4) delay(100) out(5) } out(6) } out(7) }
  4. Suspension fun order() { out(0) viewModelScope.launch { out(1) launch {

    out(2) delay(100) out(3) } launch { out(4) delay(100) out(5) } out(6) } out(7) }
  5. Suspension fun order() { out(0) viewModelScope.launch { out(1) launch {

    out(2) delay(100) out(3) } launch { out(4) delay(100) out(5) } out(6) } out(7) }
  6. Suspension fun order() { out(0) viewModelScope.launch { out(1) launch {

    out(2) delay(100) out(3) } launch { out(4) delay(100) out(5) } out(6) } out(7) }
  7. Suspension fun order() { out(0) viewModelScope.launch { out(1) launch {

    out(2) delay(100) out(3) } launch { out(4) delay(100) out(5) } out(6) } out(7) }
  8. Suspension fun order() { out(0) viewModelScope.launch { out(1) launch {

    out(2) delay(100) out(3) } launch { out(4) delay(100) out(5) } out(6) } out(7) }
  9. Suspension fun order() { out(0) viewModelScope.launch { out(1) launch {

    out(2) delay(100) out(3) } launch { out(4) delay(100) out(5) } out(6) } out(7) }
  10. Suspension fun order() { out(0) viewModelScope.launch { out(1) launch {

    out(2) delay(100) out(3) } launch { out(4) delay(100) out(5) } out(6) } out(7) }
  11. Suspension fun order() { out(0) viewModelScope.launch { out(1) launch {

    out(2) delay(100) out(3) } launch { out(4) delay(100) out(5) } out(6) } out(7) }
  12. Suspension fun order() { out(0) viewModelScope.launch { out(1) launch {

    out(2) delay(100) out(3) } launch { out(4) delay(100) out(5) } out(6) } out(7) }
  13. Suspension fun order() { out(0) viewModelScope.launch { out(1) launch {

    out(2) delay(100) out(3) } launch { out(4) delay(100) out(5) } out(6) } out(7) }
  14. Suspension fun order() { out(0) viewModelScope.launch { out(1) launch {

    out(2) delay(100) out(3) } launch { out(4) delay(100) out(5) } out(6) } out(7) }
  15. Suspension fun order() { out(0) viewModelScope.launch { out(1) launch {

    out(2) delay(100) out(3) } launch { out(4) delay(100) out(5) } out(6) } out(7) }
  16. Suspension fun order() { out(0) viewModelScope.launch { out(1) launch {

    out(2) delay(100) out(3) } launch { out(4) delay(100) out(5) } out(6) } out(7) }
  17. Suspension fun order() { out(0) viewModelScope.launch { out(1) launch {

    out(2) delay(100) out(3) } launch { out(4) delay(100) out(5) } out(6) } out(7) } // 0, 1, 6, 2, 4, 7, 3, 5
  18. Suspension fun order() { out(0) viewModelScope.launch { out(1) launch {

    out(2) delay(100) out(3) } launch { out(4) delay(100) out(5) } out(6) } out(7) } // 0, 1, 6, 2, 4, 7, 3, 5
  19. Suspension Lets look closer at the continuation in action with

    the suspendCancellableCoroutine function. fun simpleContinuation() { viewModelScope.launch { out(1) suspendCancellableCoroutine<Int> { out(2)
 it.resumeWith(Result.success(2)) } out(3) } }
  20. Suspension Use suspendCancellableCoroutine instead of suspendCoroutine, Useful when bridging between

    callbacks and coroutines. They are suspending functions, and as all suspending functions - they need to be called from a suspending function, and so on. So where to start?
  21. Scope A very small interface, only holding a reference to

    the context. Don't be afraid to create them - they are not dangerous. Look at viewModelScope to see an example used a lot But don't overuse them
  22. Context Simpli fi ed - A HashMap of Contexts We

    need a context - it de fi nes the rules for our coroutine We can override any value of the context Job, Dispatchers, CoroutineExceptionHandler, CoroutineName to name a few
  23. Structured concurrency An important and often overlooked part of coroutines.

    Our builders are extension functions to the CoroutineScope. Creating a new coroutine (invoking a builder) inherits the context and creates a parent/child relationship. Each coroutine awaits it’s children before completing
  24. Job

  25. Job Has a lifecycle dictating the state Each coroutine has

    it’s own job! It’s the only context that isn’t inherited 
 - each coroutine creates Its own instance with the inherited as its parent. Creating the hierarchy needed for structured concurrency
  26. Job Has a lifecycle dictating the state Each coroutine has

    it’s own job! It’s the only context that isn’t inherited 
 - each coroutine creates Its own instance with the inherited (or overridden) as its parent. Creating the hierarchy needed for structured concurrency
  27. Job wait children +-----+ start +--------+ complete +-------------+ finish +-----------+

    | New | -----> | Active | --------> | Completing | -------> | Completed | +-----+ +--------+ +-------------+ +-----------+ | cancel / fail | | +----------------+ | | V V +------------+ finish +-----------+ | Cancelling | -------------------------------> | Cancelled | +------------+ +-----------+
  28. Streams Flows Flows adhere to the general cooperative cancellation of

    coroutines. As usual, fl ow collection can be cancelled when the fl ow is suspended in a cancellable suspending function (like delay). Channels Note: Ticker channels are not currently integrated with structured concurrency and their api will change in the future.
  29. Suspension
 - They de fi ne the units of code


    - suspendCancellableCoroutine
 - Can only be called from other suspending functions Scope
 - They are the logical root of coroutines
 - Needed for builders
 - Cancel children, not the scope
 - Think of viewModelScope when in doubt. Structured concurrency
 - Understand it! Utilize it!
 - Even children with di ff erent dispatchers are awaited
 - Don’t think in callbacks. Job
 - The controller of structured concurrency
 - Understand the lifecycle
 - Be ware of creation to not outplay the structure
 - One coroutine - One Job Sum up
  30. Cancellation
 - They are collaborative - on suspension
 - Remember

    to re-trow them Exceptions
 - SupervisorJob / Job di ff erences
 - Use supervisorScope instead of creating jobs.
 - Propagates to the root (scope’s handler)
 - withContext(NonCancellable) Streams
 - Flows are built on top of coroutines
 - Channels are used to communicate between coroutines
 - Channels can’t broadcast
 - Mind context and use fl owOn
 - Think about order when collecting fl ows Sum up