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

Coroutines in Kotlin v2

Coroutines in Kotlin v2

Slides from my talk at KyivAndroidDevClub #12, 2017-11-11

Dmytro Zaitsev

November 11, 2017
Tweet

More Decks by Dmytro Zaitsev

Other Decks in Programming

Transcript

  1. v1: Sequential fun postItem(item: Item) {
 val token = prepareToken()

    / / 1
 val post = submitPost(token, item) / / 2
 processPost(post) / / 3
 }
  2. v2: Async callbacks fun postItem(item: Item) {
 prepareTokenAsync { token

    -> / / 1
 submitPostAsync(token, item) { post -> / / 2
 processPost(post) / / 3
 }
 }
 }
  3. v3: Reactive (Future-based) fun postItem(item: Item) {
 observeToken()
 .concatMap {

    token -> observePost(token, item) }
 .subscribe { post -> processPost(post) }
 }
  4. v4: Coroutines fun postItem(item: Item) = launch {
 val token

    = prepareToken() / / 1
 val post = submitPost(token, item) / / 2
 processPost(post) / / 3
 }
 }
  5. Experimental status New style of programming The design is not

    final and expected to change JetBrains still collects information and feedbacks Can and should be used in production Backwards compatibility guaranteed
  6. A coroutine is… an instance of suspendable computation similar to

    a daemon thread, but very light-weight similar to a future or promise
  7. Why coroutines? threads are expensive to keep and switch your

    code is single threaded you’ve got lots of mutable states
  8. Standard API • Language support (`suspend` keyword) • low-level basic

    API (stdlib: kotlin.coroutines) • high-level APIs that can be used in user code
  9. Low-level API (kotlin.coroutines) • kotlin.coroutines.experimental • create/start/suspendCoroutine() • Continuation interface

    • @RestrictSuspension annotation • kotlin.coroutines.experimental.intrinsics • suspendCoroutineOrReturn()
  10. Continuation / / Kotlin suspend fun submitPost( token: Token, item:

    Item): Post {…} / / Java/JVM Object submitPost( Token token, Item item, Continuation<Post> cont) {…} compiler magic
  11. async/await / / C# way async Task ProcessImage(String url)
 {


    var image = await LoadImage(url);
 imageView.SetImage(image);
 } / / Kotlin way fun processImage(url: String) = async(UI) {
 val image = loadImageAsync(url).await()
 imageView.setImage(image)
 }
  12. buildSequence {
 print("Start")
 yield(1) / / suspension point
 var prev

    = 0; var cur = 1
 while (true) {
 val next = prev + cur print(“Next")
 yield(next) / / suspension point
 prev = cur; cur = next
 }
 print("End") / / unreachable code
 }.take(6).forEach { print(" $it ") }
 / / Output: Start 1 Next 1 Next 2 Next 3 Next 5 Next 8
  13. buildSequence {
 print("Start")
 yield(1) / / suspension point
 var prev

    = 0; var cur = 1
 while (true) {
 val next = prev + cur print(“Next")
 yield(next) / / suspension point
 prev = cur; cur = next
 }
 print("End") / / unreachable code
 }.take(6).forEach { print(" $it ") }
 / / Output: Start 1 Next 1 Next 2 Next 3 Next 5 Next 8
  14. buildSequence {
 print("Start")
 yield(1) / / suspension point
 var prev

    = 0; var cur = 1
 while (true) {
 val next = prev + cur print(“Next")
 yield(next) / / suspension point
 prev = cur; cur = next
 }
 print("End") / / unreachable code
 }.take(6).forEach { print(" $it ") }
 / / Output: Start 1 Next 1 Next 2 Next 3 Next 5 Next 8
  15. buildSequence {
 print("Start")
 yield(1) / / suspension point
 var prev

    = 0; var cur = 1
 while (true) {
 val next = prev + cur print(“Next")
 yield(next) / / suspension point
 prev = cur; cur = next
 }
 print("End") / / unreachable code
 }.take(6).forEach { print(" $it ") }
 / / Output: Start 1 Next 1 Next 2 Next 3 Next 5 Next 8
  16. buildSequence {
 print("Start")
 yield(1) / / suspension point
 var prev

    = 0; var cur = 1
 while (true) {
 val next = prev + cur print(“Next")
 yield(next) / / suspension point
 prev = cur; cur = next
 }
 print("End") / / unreachable code
 }.take(6).forEach { print(" $it ") }
 / / Output: Start 1 Next 1 Next 2 Next 3 Next 5 Next 8
  17. buildSequence {
 print("Start")
 yield(1) / / suspension point
 var prev

    = 0; var cur = 1
 while (true) {
 val next = prev + cur print(“Next")
 yield(next) / / suspension point
 prev = cur; cur = next
 }
 print("End") / / unreachable code
 }.take(6).forEach { print(" $it ") }
 / / Output: Start 1 Next 1 Next 2 Next 3 Next 5 Next 8
  18. kotlinx.coroutines Core integration Guava JDK 8 NIO Quasar reactive Reactor

    RxJava 1.x Reactive Streams RxJava 2.x UI Android JavaFX Swing
  19. Job states State isActive isCompleted isCancelled New - - -

    Active + - - Completed - + - Cancelling - - + Cancelled - + +
  20. val deferred = async(CommonPool) {
 throw SomeException("I'm thrown inside a

    coroutine")
 }
 try {
 deferred.await() / / re-throws
 } catch (e: SomeException) {
 log(e.message)
 } Exception handling
  21. WeakReference “life hack” suspend operator fun <T> WeakReference<T>.invoke(): T =

    suspendCoroutineOrReturn { get() ?: throw CancellationException() } val activityRef = WeakReference(this)
 launch(CommonPool) {
 activityRef().expensiveComputation()
 }
  22. Links Andrey Breslav FAQ:
 https:/ /discuss.kotlinlang.org/t/experimental-status-of-coroutines-in-1-1-and- related-compatibility-concerns/2236 Design document (KEEP):


    https:/ /github.com/Kotlin/kotlin-coroutines/blob/master/kotlin-coroutines- informal.md Full kotlinx.coroutines API:
 http:/ /kotlin.github.io/kotlinx.coroutines Coroutines guide by Roman ELizarov:
 https:/ /github.com/Kotlin/kotlinx.coroutines/blob/master/coroutines-guide.md