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

Better Async With Kotlin Coroutines

Better Async With Kotlin Coroutines

In this talk we explained how coroutines allow running an asynchronous piece of code in the same manner as you’d normally run a synchronous one. We also explained here about coroutine component, builders and other many important concepts. We have explain it real life examples.

Vrushali Raut

October 09, 2018
Tweet

More Decks by Vrushali Raut

Other Decks in Programming

Transcript

  1. Problem statement @WorkerThread fun loadWeather(city: String): List<Weather> { … }

    @MainThread fun showWeather(weather: List<Weather>) { … }
  2. Thread { code } .start() object MyTask: AsyncTask() { override

    fun doInBackground { code } override fun onPostExecute { code } } Current Callbacks
  3. Corountines It can be thought of as an instance of

    suspend-able computation non-blocking code Coroutines simplify asynchronous programming by providing possibility to write code in direct style (sequentially).
  4. Coroutine Example launch { println("CR start : ${getThreadName()}") Thread.sleep(100) println("CR

    ended : ${getThreadName()}") } run { println("Run start: ${getThreadName()}") Thread.sleep(300) println("Run ended: ${getThreadName()}") } fun funExperiment() { }
  5. Coroutine Example launch { println("CR start : ${getThreadName()}") Thread.sleep(100) println("CR

    ended : ${getThreadName()}") } run { println("Run start: ${getThreadName()}") Thread.sleep(300) println("Run ended: ${getThreadName()}") } fun funExperiment() { } Run start: main CR start : commonPool-worker-1 Output
  6. Coroutine Example launch { println("CR start : ${getThreadName()}") Thread.sleep(100) println("CR

    ended : ${getThreadName()}") } run { println("Run start: ${getThreadName()}") Thread.sleep(300) println("Run ended: ${getThreadName()}") } fun funExperiment() { } Run start: main CR start : commonPool-worker-1 Output CR ended : commonPool-worker-1 Run ended: main
  7. Coroutine Example runBlocking { launch(coroutineContext) { println("CR start : ${getThreadName()}")

    Thread.sleep(100) println(“CR ended : ${getThreadName()}") } run { println("Run start: ${getThreadName()}") Thread.sleep(300) println("Run ended: ${getThreadName()}") } } fun funExperiment() { }
  8. Coroutine Example runBlocking { launch(coroutineContext) { println("CR start : ${getThreadName()}")

    Thread.sleep(100) println(“CR ended : ${getThreadName()}") } run { println("Run start: ${getThreadName()}") Thread.sleep(300) println("Run ended: ${getThreadName()}") } } fun funExperiment() { }
  9. Coroutine Example runBlocking { launch(coroutineContext) { println("CR start : ${getThreadName()}")

    Thread.sleep(100) println(“CR ended : ${getThreadName()}") } run { println("Run start: ${getThreadName()}") Thread.sleep(300) println("Run ended: ${getThreadName()}") } } fun funExperiment() { } Run start: commonPool-worker-1 Run ended: commonPool-worker-1 CR start : commonPool-worker-1 CR ended : commonPool-worker-1 Output
  10. interface Continuation<in T> { val context: CoroutineContext fun resume(value: T)

    fun resumeWithException(exception: Throwable) } Continuation Components
  11. T Components withContext() Job launch() Deferred async() Returns result Uncaught

    exception - crash Fire and forget Uncaught exception - crash Non-Blocking future Uncaught exception - returned inside deferred
  12. public actual fun launch( context: CoroutineContext = DefaultDispatcher, start: CoroutineStart

    = CoroutineStart.DEFAULT, parent: Job? = null, block: suspend CoroutineScope.() -> Unit ): Job Builders
  13. public actual fun launch( context: CoroutineContext = DefaultDispatcher, start: CoroutineStart

    = CoroutineStart.DEFAULT, parent: Job? = null, block: suspend CoroutineScope.() -> Unit ): Job Builders
  14. public actual fun launch( context: CoroutineContext = DefaultDispatcher, start: CoroutineStart

    = CoroutineStart.DEFAULT, parent: Job? = null, block: suspend CoroutineScope.() -> Unit ): Job Builders
  15. public actual fun launch( context: CoroutineContext = DefaultDispatcher, start: CoroutineStart

    = CoroutineStart.DEFAULT, parent: Job? = null, block: suspend CoroutineScope.() -> Unit ): Job Builders
  16. public actual fun launch( context: CoroutineContext = DefaultDispatcher, start: CoroutineStart

    = CoroutineStart.DEFAULT, parent: Job? = null, block: suspend CoroutineScope.() -> Unit ): Job Builders
  17. public actual fun launch( context: CoroutineContext = DefaultDispatcher, start: CoroutineStart

    = CoroutineStart.DEFAULT, parent: Job? = null, block: suspend CoroutineScope.() -> Unit ): Job Builders
  18. The plan 1. start coroutine 2. var apiData = fetchDataFromServer().await()

    3. var result = parseData(apiData).await() 4. displayInList(data)
  19. val job = launch(context = CommonPool) { val weatherResult =

    loadWeather("Bengaluru") launch(context = UI) { showWeather(weatherResult) } } Solution 1
  20. val job = launch(context = CommonPool) { val weatherResult =

    loadWeather("Bengaluru") launch(context = UI) { showWeather(weatherResult) } } Another Coroutine Solution 1
  21. Solution 1 job.cancel() val job = launch(context = CommonPool) {

    val weatherResult = loadWeather("Bengaluru") launch(context = UI) { showWeather(weatherResult) } }
  22. • Simpler thread switching • Simple DSL • Dancing with

    final code Coroutines The fun Solution
  23. Solution fun getWeather(city="Bengaluru") { async(context = UI) { view.showLoading() val

    result = withContext(bgContext) { loadWeather(city) } showWeather(result) } }
  24. Solution fun getWeather(city="Bengaluru") { async(context = UI) { view.showLoading() val

    result = withContext(bgContext) { loadWeather(city) } showWeather(result) } }
  25. fun getWeather(city="Bengaluru") { async(context = UI) { view.showLoading() val result

    = withContext(bgContext) { loadWeather(city) } showWeather(result) } } Solution
  26. Solution fun getWeather(city="Bengaluru") { async(context = UI) { view.showLoading() val

    result = withContext(bgContext) { loadWeather(city) } showWeather(result) } }
  27. Where we were @WorkerThread fun loadWeather(city: String): List<Weather> { …

    } @MainThread fun showWeather(weather: List<Weather>) { … }
  28. Fun DSL’s suspend fun <T> load(block: () -> T): Deferred<T>

    { } return block() fun <T> Deferred<T>.thenOnUI(uiFunction: (T) -> Unit) { } launch(UI) { uiFunction([email protected]()) }