Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
KOTLIN COROUTINES AND ANDROID
SITTING IN A TREE...
KAI KOENIG (@AGENTK)
HELLO
HELLO
My name is Kai!
Software Architect in the web and mobile (Android) space 

from New Zealand.
Stuff I enjoy: An...
AGENDA
AGENDA
▸ Kotlin in 5 minutes
▸ Why coroutines?
▸ Using coroutines in your Kotlin code
▸ Libraries and coroutines on...
KOTLIN IN 5 MINUTES
https://www.flickr.com/photos/tschiae/8080742303/
HISTORY OF KOTLIN (I)
▸ Jetbrains wanted a more efficient JVM language when building products
▸ Looked at Scala, Groovy, et...
HISTORY OF KOTLIN (II)
▸ Since 1.0 release in early 2016:
▸ multiple maintenance releases
▸ now at 1.0.7
▸ 1.1 was release...
HISTORY OF KOTLIN (III)
▸ At Google IO 2017, Kotlin became a first-grade language for Android
▸ Development of 1.2 is under...
KOTLIN IN 5 MINUTES
PROMINENT LANGUAGE FEATURES
▸ Immutability
▸ String templates
▸ Explicit null handling
▸ Properties an...
THE 1.1 RELEASE
OVERVIEW
▸ JavaScript target is not experimental anymore (browser & NodeJS)
▸ Full Kotlin language support...
WHY COROUTINES?
https://www.flickr.com/photos/61299367@N05/9448165205
WHY COROUTINES?
MOTIVATION
▸ Asynchronous programming is becoming increasingly important
▸ Problem: the need to avoid bloc...
http://slides.com/michaelholroyd/asyncnodejs/#/
WHY COROUTINES?
HISTORY
▸ Coroutines were first mentioned and used in Simula 67
▸ detach & resume keywords to suspend and t...
WHY COROUTINES?
COROUTINES IN KOTLIN (I)
▸ Kotlin’s approach: Suspending functions
▸ Function/lambda that can be suspended...
WHY COROUTINES?
COROUTINES IN KOTLIN (II)
▸ Easiest way to think about a coroutine is a very light-weighted thread
▸ They ...
WHY COROUTINES?
COROUTINES IN KOTLIN (III)
▸ Multiple layers of libraries and integration points:
▸ Language support: susp...
USING COROUTINES IN
YOUR KOTLIN CODE
https://www.flickr.com/photos/97114911@N05/14720054418
USING COROUTINES IN YOUR KOTLIN CODE
FUNDAMENTALS
▸ Use Kotlin 1.1.4 as a minimum, better 1.1.51
▸ Enable experimental fea...
USING COROUTINES IN YOUR KOTLIN CODE
“HELLO WORLD”
▸ launch {…} starts new coroutine on CommonPool thread pool
▸ delay() i...
USING COROUTINES IN YOUR KOTLIN CODE
“HELLO WORLD” IN BETTER
▸ Wait for the coroutines to finish - launch {…} returns a Job...
USING COROUTINES IN YOUR KOTLIN CODE
THREADS VS COROUTINES
import java.util.concurrent.atomic.AtomicInteger
import kotlin....
import kotlinx.coroutines.experimental.*
import java.util.concurrent.atomic.AtomicInteger
fun main(args: Array<String>) {
...
USING COROUTINES IN YOUR KOTLIN CODE
ASYNC/AWAIT (I)
▸ async {…} starts new coroutine and returns a Deferred<T> object
▸ D...
USING COROUTINES IN YOUR KOTLIN CODE
ASYNC/AWAIT (II)
import kotlinx.coroutines.experimental.*
fun main(args: Array<String...
USING COROUTINES IN YOUR KOTLIN CODE
SUSPEND FUNCTIONS (I)
▸ Coroutines can suspend without blocking a thread
▸ Functions ...
USING COROUTINES IN YOUR KOTLIN CODE
SUSPEND FUNCTIONS (II)
fun main(args: Array<String>) {
val deferred = (1..1_000_000)....
USING COROUTINES IN YOUR KOTLIN CODE
BEHIND THE SCENES
▸ Kotlin coroutines are very light on language features:
▸ suspend ...
USING COROUTINES IN YOUR KOTLIN CODE
MORE BEHIND THE SCENES
▸ At compilation:
▸ Suspending functions compile to functions ...
USING COROUTINES IN YOUR KOTLIN CODE
LAUNCH VS ASYNC
▸ Conceptually very similar
▸ launch {…} returns a Job, no resulting ...
USING COROUTINES IN YOUR KOTLIN CODE
WAITING AND CANCELLING
▸ cancel() and then join() can be used to terminate a coroutin...
USING COROUTINES IN YOUR KOTLIN CODE
DEALING WITH TIMEOUTS
▸ Quite often the motivation for cancelling is a timeout:
▸ Tra...
USING COROUTINES IN YOUR KOTLIN CODE
THAT’S NOT ALL OF IT YET
▸ Coroutine context
▸ Coroutines and threads
▸ Channels
▸ Pi...
LIBRARIES AND
COROUTINES ON
ANDROID
https://www.flickr.com/photos/qiaomeng/4665885561/
MOTIVATION
▸ In general, UI-driven apps need to be aware of long-running processes
▸ In Android specifically, we can’t do a...
UI CONTEXT
▸ The Android library provides access to a coroutine context for the UI thread
▸ Coroutine launches in UI threa...
OTHER UI THREAD CONCERNS
▸ For Jobs and cancelling coroutines, the same general principles still apply
▸ using launch {…} ...
OTHER UI THREAD CONCERNS
▸ Interesting topics for further study:
▸ Limit and manage coroutines via actors
▸ Dealing with e...
THREAD BLOCKING OPERATIONS AND THE UI
▸ CPU-intensive computations and/or API calls
▸ Can’t be done from UI thread or UI t...
NETWORK CALLS (I)
▸ Callback-free API call, handle offline-exceptions
LIBRARIES AND COROUTINES ON ANDROID
fun getUsers() : ...
NETWORK CALLS (II)
▸ Handle exceptions in calling code
▸ Use result object’s await() to obtain the data (suspending the co...
ANKO
▸ More often than not identified with declarative UI for Android/Kotlin
▸ But it also has APIs for:
▸ Async
▸ SQLite
▸...
LIBRARIES AND COROUTINES ON ANDROID
COROUTINES IN ANKO
▸ Add anko-coroutines dependency
▸ Earlier versions of Anko already...
LIBRARIES AND COROUTINES ON ANDROID
COROUTINES WITH ASYNCAWAIT
▸ Async/await approach
▸ Very rich library on top of Kotlin...
OTHER THINGS AND
FINAL THOUGHTS
https://www.flickr.com/photos/chrispiascik/4054331891
OTHER THINGS & FINAL THOUGHTS
UNIT TESTING SUSPENDING FUNCTIONS
▸ They need a coroutine to run, easiest way seems to be wi...
OTHER THINGS & FINAL THOUGHTS
EXPERIMENTAL?
▸ Coroutines are experimental in Kotlin 1.1.x, however:
▸ Very sound approach ...
OTHER THINGS
RESOURCES
▸ Coroutines design document:

https://github.com/Kotlin/kotlin-coroutines
▸ Coroutines guide:

htt...
OTHER THINGS
GET IN TOUCH
Kai Koenig
Email: kai@ventego-creative.co.nz
Work: http://www.ventego-creative.co.nz
Twitter: @A...
Kotlin Coroutines and Android sitting in a tree
Upcoming SlideShare
Loading in …5
×

Kotlin Coroutines and Android sitting in a tree

621 views

Published on

Since the release of Kotlin 1.1 there is now the new language feature of Kotlin Coroutines available for use in Java and Android projects. Coroutines are a new way to write asynchronous and non-blocking code. They can be thought of as light-weight threads without having to deal with all the problems that threads bring to the table.

A lot of developers think that Kotlin Coroutines are mainly or only useful for Kotlin on the JVM, but that’s not true. There are a variety of use cases in which the application of Coroutines can make a lot of sense on Android.

This talk is introducing the ideas behind Kotlin Coroutines, showing how to use them in Kotlin code for both the JVM and Android via the kotlinx-coroutines APIs and then exploring specific applications in Android. Part of this is a deeper look into the use of Coroutines in higher-level frameworks such as AsyncAwait and Anko.

Published in: Software
  • Be the first to comment

  • Be the first to like this

Kotlin Coroutines and Android sitting in a tree

  1. 1. KOTLIN COROUTINES AND ANDROID SITTING IN A TREE... KAI KOENIG (@AGENTK)
  2. 2. HELLO HELLO My name is Kai! Software Architect in the web and mobile (Android) space 
 from New Zealand. Stuff I enjoy: Android, Kotlin, CFML, compilers and parsers, aviation and flying small aircraft, cats and chickens, Nintendo video games of all ages! Twitter: @AgentK
  3. 3. AGENDA AGENDA ▸ Kotlin in 5 minutes ▸ Why coroutines? ▸ Using coroutines in your Kotlin code ▸ Libraries and coroutines on Android
  4. 4. KOTLIN IN 5 MINUTES https://www.flickr.com/photos/tschiae/8080742303/
  5. 5. HISTORY OF KOTLIN (I) ▸ Jetbrains wanted a more efficient JVM language when building products ▸ Looked at Scala, Groovy, etc. but came up with their own language spec ▸ First shown at the JVM Language Summit in 2011 ▸ Got some traction in Android-land in 2014 ▸ Modern language features (lambdas, HOF etc) but Java 6 byte code ▸ Low methods count (~7000) ▸ Strong focus on concision and an efficient, bloat-free language KOTLIN IN 5 MINUTES
  6. 6. HISTORY OF KOTLIN (II) ▸ Since 1.0 release in early 2016: ▸ multiple maintenance releases ▸ now at 1.0.7 ▸ 1.1 was released in Feb 2017, ▸ currently at 1.1.51 (previously 1.1.5-1) KOTLIN IN 5 MINUTES
  7. 7. HISTORY OF KOTLIN (III) ▸ At Google IO 2017, Kotlin became a first-grade language for Android ▸ Development of 1.2 is underway ▸ Java 9 compatibility ▸ Multiplatform projects ▸ Huge improvements to StdLib, type inference, smart cast etc. ▸ Strong community, lots of interesting frameworks, awesome support from Jetbrains KOTLIN IN 5 MINUTES
  8. 8. KOTLIN IN 5 MINUTES PROMINENT LANGUAGE FEATURES ▸ Immutability ▸ String templates ▸ Explicit null handling ▸ Properties and Fields ▸ Data classes ▸ Extension functions ▸ Syntactic sugar ▸ Type inference ▸ Lambdas ▸ Collection API ▸ Type-safe builders ▸ Java-Kotlin-Interop
  9. 9. THE 1.1 RELEASE OVERVIEW ▸ JavaScript target is not experimental anymore (browser & NodeJS) ▸ Full Kotlin language support ▸ Large part of the stdlib is supported ▸ Coroutines (JVM-only, experimental) ▸ Lightweight concurrency mechanism ▸ Alternative to threads ▸ Tooling improvements & more language features
  10. 10. WHY COROUTINES? https://www.flickr.com/photos/61299367@N05/9448165205
  11. 11. WHY COROUTINES? MOTIVATION ▸ Asynchronous programming is becoming increasingly important ▸ Problem: the need to avoid blocking introduces a lot of complexity ▸ Threads are: ▸ expensive to manage and limited ▸ complex in applications with lots of mutable state ▸ usually even more complex to deal with in UI-driven applications ▸ Callback hell (very common in Javascript)
  12. 12. http://slides.com/michaelholroyd/asyncnodejs/#/
  13. 13. WHY COROUTINES? HISTORY ▸ Coroutines were first mentioned and used in Simula 67 ▸ detach & resume keywords to suspend and then later resume execution ▸ Pushed aside by industry trend towards multi-threading ▸ C# has async/await ▸ Go was one of the first modern languages re-introducing coroutines
  14. 14. WHY COROUTINES? COROUTINES IN KOTLIN (I) ▸ Kotlin’s approach: Suspending functions ▸ Function/lambda that can be suspended and resumed ▸ No context-switching on the OS level ▸ Minimal integration into the core language and stdlib, most of functionality provided by libraries ▸ Design allows for a variety of asynchronous API methodologies to be implemented on top of Kotlin coroutines ▸ Supposed to feel like writing traditional code
  15. 15. WHY COROUTINES? COROUTINES IN KOTLIN (II) ▸ Easiest way to think about a coroutine is a very light-weighted thread ▸ They can run in parallel ▸ Coroutines can wait for each other ▸ They can communicate with each other ▸ Very, very cheap to create (compared to threads) ▸ A thread can run a lot of coroutines
  16. 16. WHY COROUTINES? COROUTINES IN KOTLIN (III) ▸ Multiple layers of libraries and integration points: ▸ Language support: suspending functions ▸ Low-level library in kotlinx.coroutines ▸ Mid-level library in kotlinx.coroutines ▸ High-level libraries (Anko etc.)
  17. 17. USING COROUTINES IN YOUR KOTLIN CODE https://www.flickr.com/photos/97114911@N05/14720054418
  18. 18. USING COROUTINES IN YOUR KOTLIN CODE FUNDAMENTALS ▸ Use Kotlin 1.1.4 as a minimum, better 1.1.51 ▸ Enable experimental feature in Gradle kotlin { experimental { coroutines 'enable' } } compile 'org.jetbrains.kotlinx:kotlinx-coroutines-core:0.19.2'
  19. 19. USING COROUTINES IN YOUR KOTLIN CODE “HELLO WORLD” ▸ launch {…} starts new coroutine on CommonPool thread pool ▸ delay() is a suspending function (not blocking a thread) fun main(args: Array<String>) { println("Start on main thread") launch(CommonPool) { delay(5000) println("Hello from coroutine") } Thread.sleep(10000) println("Stop on main thread") }
  20. 20. USING COROUTINES IN YOUR KOTLIN CODE “HELLO WORLD” IN BETTER ▸ Wait for the coroutines to finish - launch {…} returns a Job object fun main(args: Array<String>) = runBlocking { println("Start on main thread") val job = launch(CommonPool) { delay(5000) println("Hello from coroutine") } job.join() println("Stop on main thread") }
  21. 21. USING COROUTINES IN YOUR KOTLIN CODE THREADS VS COROUTINES import java.util.concurrent.atomic.AtomicInteger import kotlin.concurrent.thread fun main(args: Array<String>) { val c = AtomicInteger() for (i in 1..1_000_000) thread(start = true) { c.addAndGet(i) } println(c.get()) }
  22. 22. import kotlinx.coroutines.experimental.* import java.util.concurrent.atomic.AtomicInteger fun main(args: Array<String>) { val c = AtomicInteger() for (i in 1..1_000_000) launch(CommonPool) { c.addAndGet(i) } // Temporary hack to allow the coroutines to finish Thread.sleep(2000) println(c.get()) } USING COROUTINES IN YOUR KOTLIN CODE THREADS VS COROUTINES
  23. 23. USING COROUTINES IN YOUR KOTLIN CODE ASYNC/AWAIT (I) ▸ async {…} starts new coroutine and returns a Deferred<T> object ▸ Deferred<T>.await() returns result of the coroutine ▸ await() needs to be called from inside a coroutine, because it needs to suspend in a non-blocking way ▸ Solution: wrap into runBlocking {…} coroutine ▸ Starts coroutine and wait until it’s finished
  24. 24. USING COROUTINES IN YOUR KOTLIN CODE ASYNC/AWAIT (II) import kotlinx.coroutines.experimental.* fun main(args: Array<String>) { val deferred = (1..1_000_000).map { n -> async (CommonPool) { n } } runBlocking { val sum = deferred.sumBy { it.await() } println("Sum: $sum") } }
  25. 25. USING COROUTINES IN YOUR KOTLIN CODE SUSPEND FUNCTIONS (I) ▸ Coroutines can suspend without blocking a thread ▸ Functions that might suspend need to be marked with the suspend keyword ▸ They can only be called from another suspend function or a coroutine
  26. 26. USING COROUTINES IN YOUR KOTLIN CODE SUSPEND FUNCTIONS (II) fun main(args: Array<String>) { val deferred = (1..1_000_000).map { n -> async (CommonPool) { doWork(n) } } runBlocking { ... } } suspend fun doWork(n: Int) : Int { delay(50) return n }
  27. 27. USING COROUTINES IN YOUR KOTLIN CODE BEHIND THE SCENES ▸ Kotlin coroutines are very light on language features: ▸ suspend the only new keyword added to the language and acts pretty much like a compiler flag ▸ Continuation and CoroutineContext in stdlib ▸ All the rest is in the kotlinx.coroutines library This makes the design of Kotlin coroutines very composable.
  28. 28. USING COROUTINES IN YOUR KOTLIN CODE MORE BEHIND THE SCENES ▸ At compilation: ▸ Suspending functions compile to functions with a general callback interface of type Continuation ▸ Code with suspension points compiles to state machine ▸ launch, runBlocking, async etc. are often called coroutine builders
  29. 29. USING COROUTINES IN YOUR KOTLIN CODE LAUNCH VS ASYNC ▸ Conceptually very similar ▸ launch {…} returns a Job, no resulting value ▸ async {…} returns a Deferred - a future that can be used to obtain a value ▸ async generally suited better in situations with independent concurrent flows
  30. 30. USING COROUTINES IN YOUR KOTLIN CODE WAITING AND CANCELLING ▸ cancel() and then join() can be used to terminate a coroutine execution early ▸ Job has an extension function cancelAndJoin() doing both at once val job = launch { repeat(1000) { i -> println("job: I'm sitting here and delaying $i ...") delay(500L) } } delay(1300L) println("main: I'm really over waiting!") job.cancel() job.join() // or use: job.cancelAndJoin() println("main: Let's go.")
  31. 31. USING COROUTINES IN YOUR KOTLIN CODE DEALING WITH TIMEOUTS ▸ Quite often the motivation for cancelling is a timeout: ▸ Track yourself via the Job instance ▸ Use withTimeout() {…} withTimeout(1300L) { repeat(1000) { i -> println("I'm waiting $i ...") delay(500L) } }
  32. 32. USING COROUTINES IN YOUR KOTLIN CODE THAT’S NOT ALL OF IT YET ▸ Coroutine context ▸ Coroutines and threads ▸ Channels ▸ Pipelines ▸ Dealing with state ▸ Shared (mutable) state & Actors Compare Coroutines with Java Futures API
  33. 33. LIBRARIES AND COROUTINES ON ANDROID https://www.flickr.com/photos/qiaomeng/4665885561/
  34. 34. MOTIVATION ▸ In general, UI-driven apps need to be aware of long-running processes ▸ In Android specifically, we can’t do any networking on the UI thread. ▸ The kotlinx.coroutines library by Jetbrains provides a starting point for Android, too. LIBRARIES AND COROUTINES ON ANDROID compile 'org.jetbrains.kotlinx:kotlinx-coroutines-android:0.19.2'
  35. 35. UI CONTEXT ▸ The Android library provides access to a coroutine context for the UI thread ▸ Coroutine launches in UI thread, UI updates and suspending functions are possible ▸ Non-blocking, UI is not frozen LIBRARIES AND COROUTINES ON ANDROID launch(UI) { for (i in 10 downTo 1) { hello.text = "Countdown $i ..." delay(500) } hello.text = "Done!" }
  36. 36. OTHER UI THREAD CONCERNS ▸ For Jobs and cancelling coroutines, the same general principles still apply ▸ using launch {…} provides a reference to a Job ▸ can be cancelled with cancel() - for instance via UI control ▸ In UI scenarios useful to write own coroutines builders as extension functions LIBRARIES AND COROUTINES ON ANDROID button.onClick { ... } fun View.onClick(action: suspend () -> Unit) { setOnClickListener { launch(UI) { action() } } }
  37. 37. OTHER UI THREAD CONCERNS ▸ Interesting topics for further study: ▸ Limit and manage coroutines via actors ▸ Dealing with event conflation ▸ Channel.CONFLATED ▸ Channel.UNLIMITED LIBRARIES AND COROUTINES ON ANDROID
  38. 38. THREAD BLOCKING OPERATIONS AND THE UI ▸ CPU-intensive computations and/or API calls ▸ Can’t be done from UI thread or UI thread-confined coroutine ▸ Solution: suspending functions with execution context CommonPool LIBRARIES AND COROUTINES ON ANDROID suspend fun fib(x: Int): Int = run(CommonPool) { fibBlocking(x) } fun fibBlocking(x: Int): Int = if (x <= 1) 1 else fibBlocking(x - 1) + fibBlocking(x - 2)
  39. 39. NETWORK CALLS (I) ▸ Callback-free API call, handle offline-exceptions LIBRARIES AND COROUTINES ON ANDROID fun getUsers() : Deferred<List<Users>> { return async(CommonPool) { val request = Request.Builder().url(<SOMEURL>).build() val response = OkHttpClient().newCall(request).execute() // parse response... } }
  40. 40. NETWORK CALLS (II) ▸ Handle exceptions in calling code ▸ Use result object’s await() to obtain the data (suspending the coroutine) ▸ Use launch {…} builder to trigger execution of getUsers LIBRARIES AND COROUTINES ON ANDROID launch(UI) { try { val result = getUsers() adapter.setElements(result.await()) ... } catch (exception: IOException){ // we’re offline }
  41. 41. ANKO ▸ More often than not identified with declarative UI for Android/Kotlin ▸ But it also has APIs for: ▸ Async ▸ SQLite ▸ Anko 0.9 introduced naming changes around the Async API ▸ Since Anko 0.10, Anko has support for coroutines LIBRARIES AND COROUTINES ON ANDROID
  42. 42. LIBRARIES AND COROUTINES ON ANDROID COROUTINES IN ANKO ▸ Add anko-coroutines dependency ▸ Earlier versions of Anko already had support for async handling ▸ New: ▸ Coroutines in listeners ▸ bg() ▸ asReference() fun getData(): Data { ... } fun showData(data: Data) { ... } async(UI) { val data: Deferred<Data> = bg { // Runs on the background getData() } // This code is executed on the UI thread showData(data.await()) }
  43. 43. LIBRARIES AND COROUTINES ON ANDROID COROUTINES WITH ASYNCAWAIT ▸ Async/await approach ▸ Very rich library on top of Kotlin’s coroutine core ▸ Plugins for Retrofit and rxJava async { val result = await { //Long running code } // Use result } async { val repos = await { github.getRepos() } showList(repos) repos.forEach { repo -> val stats = await { github.getStats (repo.name) } showStats(repo, stats) } }
  44. 44. OTHER THINGS AND FINAL THOUGHTS https://www.flickr.com/photos/chrispiascik/4054331891
  45. 45. OTHER THINGS & FINAL THOUGHTS UNIT TESTING SUSPENDING FUNCTIONS ▸ They need a coroutine to run, easiest way seems to be with runBlocking {…} import kotlinx.coroutines.experimental.runBlocking import org.testng.annotations.Test class MyTest { @Test fun testMySuspendingFunction() = runBlocking<Unit> { // your test code here } }
  46. 46. OTHER THINGS & FINAL THOUGHTS EXPERIMENTAL? ▸ Coroutines are experimental in Kotlin 1.1.x, however: ▸ Very sound approach of dealing with concurrency ▸ Jetbrains guarantees backwards compatibility ▸ Potentially no forward compatibility ▸ Coroutines can and should be used in production
  47. 47. OTHER THINGS RESOURCES ▸ Coroutines design document:
 https://github.com/Kotlin/kotlin-coroutines ▸ Coroutines guide:
 https://github.com/Kotlin/kotlinx.coroutines/blob/master/coroutines-guide.md ▸ Java Futures & Coroutines:
 https://blog.frankel.ch/concurrency-java-futures-kotlin-coroutines/#gsc.tab=0 ▸ Anko: 
 https://github.com/Kotlin/anko ▸ AsyncAwait:
 https://github.com/metalabdesign/AsyncAwait
  48. 48. OTHER THINGS GET IN TOUCH Kai Koenig Email: kai@ventego-creative.co.nz Work: http://www.ventego-creative.co.nz Twitter: @AgentK Telegram: @kaikoenig Slides: http://www.slideshare.com/agentk

×