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

Introduction to Kotlin Coroutines

Introduction to Kotlin Coroutines

Brief introduction to Kotlin Coroutines, presented before a workshop of introduction to Coroutines

David González

February 27, 2019
Tweet

More Decks by David González

Other Decks in Programming

Transcript

  1. Solution 2: async / await async(UI) { val image =

    loadImageAsync(url).await() setImage(image) }
  2. Coroutines are like lightweight threads Coroutine is a sequence of

    instructions Multiple coroutines can be executed concurrently Share resources such as memory
  3. Our first coroutine fun main() { GlobalScope.launch { // launch

    new coroutine in background and continue delay(1000L) // non-blocking delay for 1 second (default time unit is ms) println("World!") // print after delay } println("Hello,") // main thread continues while coroutine is delayed } Hello, World!
  4. Suspending function A function that can suspend the execution of

    a coroutine It can be started, paused and resumed at a later time Can only be called within a coroutine or from another suspending function
  5. Our first coroutine fun main() { GlobalScope.launch { // launch

    new coroutine in background and continue delay(1000L) // non-blocking delay for 1 second (default time unit is ms) println("World!") // print after delay } println("Hello,") // main thread continues while coroutine is delayed }
  6. Our first suspending function fun main() { launch { doWorld()

    } println("Hello,") } // this is your first suspending function suspend fun doWorld() { delay(1000L) println("World!") } Hello, World!
  7. Composing suspending functions suspend fun doSomethingUsefulOne(): Int { delay(1000L) //

    pretend we are doing something useful here return 13 } suspend fun doSomethingUsefulTwo(): Int { delay(1000L) // pretend we are doing something useful here, too return 29 }
  8. Composing suspending functions fun main() = runBlocking<Unit> { val time

    = measureTimeMillis { val one = doSomethingUsefulOne() val two = doSomethingUsefulTwo() println("The answer is ${one + two}") } println("Completed in $time ms") } The answer is 42 Completed in 2017 ms
  9. Composing suspending functions fun main() = runBlocking<Unit> { val time

    = measureTimeMillis { val one = async { doSomethingUsefulOne() } val two = async { doSomethingUsefulTwo() } println("The answer is ${one.await() + two.await()}") } println("Completed in $time ms") } The answer is 42 Completed in 1017 ms
  10. Coroutine Scope Defines a scope for new coroutines A scope

    controls the lifetime of coroutines through its job Every coroutine builder is an extension on CoroutineScope and inherits its coroutineContext to automatically propagate both context elements and cancellation.
  11. Composing suspending functions fun main() = runBlocking<Unit> { val time

    = measureTimeMillis { val one = async { doSomethingUsefulOne() } val two = async { doSomethingUsefulTwo() } println("The answer is ${one.await() + two.await()}") } println("Completed in $time ms") }
  12. Composing suspending functions suspend fun concurrentSum(): Int = coroutineScope {

    val one = async { doSomethingUsefulOne() } val two = async { doSomethingUsefulTwo() } one.await() + two.await() } fun main() = runBlocking<Unit> { val time = measureTimeMillis { println("The answer is ${concurrentSum()}") } println("Completed in $time ms") } The answer is 42 Completed in 1017 ms
  13. Coroutine Dispatchers Determines the thread a coroutine runs on It

    can confine a coroutine to a specific thread, a threadpool or let it run unconfined
  14. Coroutine Dispatchers fun main() = runBlocking<Unit> { launch(Dispatchers.Main) { //

    context of the parent, main runBlocking coroutine println("main runBlocking : I'm working in thread ${Thread.currentThread().name}") } launch(Dispatchers.Unconfined) { // not confined -- will work with main thread println("Unconfined : I'm working in thread ${Thread.currentThread().name}") } launch(Dispatchers.Default) { // will get dispatched to DefaultDispatcher println("Default : I'm working in thread ${Thread.currentThread().name}") } launch(newSingleThreadContext("MyOwnThread")) { // will get its own new thread println("newSingleThreadContext: I'm working in thread ${Thread.currentThread().name}") } }
  15. Coroutine Dispatchers main runBlocking : I 'm working in thread

    main Unconfined : I' m working in thread main Default : I 'm working in thread DefaultDispatcher-worker-1 newSingleThreadContext: I' m working in thread MyOwnThread