Pro Yearly is on sale from $80 to $50! »

Introduction to Kotlin Flow

Introduction to Kotlin Flow

5c1316478a9b5320d57dd851a258b5be?s=128

Armando Picón

June 25, 2020
Tweet

Transcript

  1. Introduction to Kotlin Flows Armando Picón Senior Android Developer at

    Cornershop Inc. @devpicon https://linktr.ee/devpicon
  2. Flows? • Kotlin Flows should be used when you need

    to return multiple asynchronously computed values • Flows are cold streams • Flow is inspired by reactive streams or reactive frameworks like RxJava
  3. Emitter Collector

  4. Emitter Collector flow{ emit() } collect()

  5. Emitter Collector flow{ emit() } collect() Flow builder

  6. Flow builders • flow{} -> most basic one, create a

    flow from the given suspendable block • flowOf() -> defines a flow emitting a fixed set of values • .asFlow() -> extension function for collections and sequences
  7. flow{ emit() } collect() Flow builder Emitter Collector

  8. flow{ emit() } collect() map{} filter{} transform{} take() Flow builder

    Emitter Collector
  9. flow{ emit() } collect() intermediate operators map{} filter{} transform{} take()

    Flow builder Emitter Collector
  10. Intermediate flow operators • map{} -> returns a flow containing

    the results of applying the given transform function to each value of the original flow • filter{} -> returns a flow containing only values of the original flow that matches the given predicate • transform{} -> it can be used to imitate simple transformations as well more complex transformations. We can emit arbitrary values an arbitrary number of times • take() -> cancel the execution of the flow when the corresponding limit is reached
  11. flow{ emit() } collect() map{} filter{} transform{} take() Flow builder

    intermediate operators Emitter Collector
  12. flow{ emit() } collect() Terminal flow operator map{} filter{} transform{}

    take() Flow builder intermediate operators Emitter Collector
  13. Terminal flow operators • collect{} -> collects the given flow

    with a provided action. If any exception occurs during collect or in the provided flow, this exception is rethrown from this method • reduce{} -> accumulates value starting with the first element and applying operation to current accumulator value and each element. Throws NoSuchElementException if flow was empty • fold{} -> accumulates value starting with initial value and applying operation current accumulator value and each element They are suspending functions that start a collection of the flow
  14. Terminal flow operators • first{} -> returns the first element

    emitted by the flow and then cancels flow's collection. Throws NoSuchElementException if the flow was empty • single{} -> awaits for one and only one value to be published. Throws NoSuchElementException for empty flow and IllegalStateException for flow that contains more than one element They are suspending functions that start a collection of the flow
  15. Terminal flow operators • toList(), toSet() -> Collects given flow

    into a destination and convert to collection They are suspending functions that start a collection of the flow
  16. Context preservation • Collections always happens in the context of

    the calling coroutine • You can’t change manually the context under a collection is being executed • Using of flowOn function is the only to change the context of the flow emission
  17. Flows are sequential • Each individual collection of a flow

    is performed sequentially unless special operators that operate on multiple flows are used. • What happens if the collector and emitter are slow?
  18. Emitter Collector delay(100) emit delay(100) println(it) delay(100) emit delay(100)

  19. Could be the sequential execution an issue? • Sequential execution

    could be an issue when both the emitter and the collector take too long to processing each element • Remember that usually the flows run under the same context into the same coroutine • Can we decouple the emitter and the collector without changing the code?
  20. Challenges to decouple the emitter and the collector • Run

    the emitter in a separate coroutine from the collector would do both concurrent • With two separate coroutines we need to establish some communication between both of them • Here is where Channels enter to scene providing a mechanism where we can send the elements from the emitter and receive them in another one, through a channel.
  21. Buffer operator • Buffers flow emissions via channel of a

    specified capacity and runs collector in a separate coroutine. Normally, flows are sequential. It means that the code of all operators is executed in the same coroutine. • The buffer operator creates a separate coroutine during execution for the flow it applies to.
  22. Emitter Collector delay(100) emit delay(100) println(it) delay(100) emit delay(100) println(it)

    delay(100) emit
  23. Composing multiple flows • zip() • combine()

  24. Flattening flows • flatMapConcat {} - transforms elements emitted by

    the original flow by applying transform, that returns another flow, and then concatenating and flattening these flows • flatMapMerge { } - transforms elements emitted by the original flow by applying transform, that returns another flow, and then merging and flattening these flows. • flatMapLatest {} - returns a flow that switches to a new flow produced by transform function every time the original flow emits a value. When the original flow emits a new value, the previous flow produced by transform block is cancelled.
  25. Composing multiple flows • zip() - combines the corresponding values

    of two flows • combine() - when flow represents the most recent value of a variable or operation, it might be needed to perform a computation that depends on the most recent values of the corresponding flows and to recompute it whenever any of the upstream flows emit a value
  26. Exception transparency • Exceptions can be rethrown using throw. •

    Exceptions can be turned into emission of values using emit from the body of catch. • Exceptions can be ignored, logged, or processed by some other code.
  27. References • Asynchronous Flow https://kotlinlang.org/docs/reference/coroutines/flow.html • Cold flows, hot channels

    https://medium.com/@elizarov/cold-flows-hot-channels-d74769805f9 • Simple design of Kotlin Flow https://medium.com/@elizarov/simple-design-of-kotlin-flow-4725e7398c4c • Kotlin Flows and Coroutines https://medium.com/@elizarov/kotlin-flows-and-coroutines-256260fb3bdb
  28. Recommended lectures • Asynchronous development in Android: RxJava vs Kotlin

    Flow https://medium.com/makingtuenti/asynchronous-development-in-android-rxja va-vs-kotlin-flow-f7fdf2e2f81b • From RxJava 2 to Kotlin Flow: Threading https://proandroiddev.com/from-rxjava-2-to-kotlin-flow-threading-8618867e1 955 • The Real Kotlin Flow benefits over RxJava https://proandroiddev.com/the-real-kotlin-flow-benefits-over-rxjava-c19b99ba 6eb9
  29. Codalot Podcast anchor.fm/codalot yt.vu/+devpicon ¡Gracias!