SlideShare a Scribd company logo
Kotlin Coroutines

Flow is coming
Kirill Rozov
krl.rozov@gmail.com
Lead Android Developer@
@kirill_rozov
android_broadcast
News for Android Devs
1. Channels

2. Flows

3. Custom operator

4. Concurrent Flow

5. Flow constraints

6. Adapter

7. Reactive Stream

8. Backpressure

9. Third paNy integrations
Agenda
Async in Kotlin
// Single value
suspend fun foo(p: Params): Value =
withContext(Dispatchers.Default) { bar(p) }
// Collection of values
suspend fun foo(p: Params): List<Value> =
buildList { while (hasMore) add(nextValue) }
// Stream of values
fun foo(p: Params): Sequence<Value> =
sequence { while (hasMore) yield(nextValue) }
Async in Kotlin
// Single value
suspend fun foo(p: Params): Value =
withContext(Dispatchers.Default) { bar(p) }
// Collection of values
suspend fun foo(p: Params): List<Value> =
buildList { while (hasMore) add(nextValue) }
// Stream of values
fun foo(p: Params): Sequence<Value> =
sequence { while (hasMore) yield(nextValue) }
Blocking
Channels
Channels
fun CoroutineScope.fooProducer(p: Params)
: ReceiveChannel<Value> {
return produce { while (hasMore) send(nextValue) }
}
Channels
fun CoroutineScope.fooProducer(p: Params)
: ReceiveChannel<Value> {
return produce { while (hasMore) send(nextValue) }
}
val values: ReceiveChannel<Value> = fooProducer(p)
if (someCondition) {
return anotherResult // Oops! Leaked channel
}
// ... do further work with values ...
• Works with data sources that are intrinsically hot

Data sources that exist without application’s requests for them

• incoming network connections

• event streams

• Synchronization primitives

• For transfer data between coroutines

• Synchronize access to the same data from multiply coroutines
Channels
Flows
Flow is a cold asynchronous data stream that
executed sequentially (in the same coroutine)
emits values and completes normally or with an
exception
kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/-flow/
GlobalScope.launch {
flowOf(1, 2, 3)
.map { it * it }
.collect { print(it) }
}
Flow
Flow
interface Flow<out T> {
suspend fun collect(collector: FlowCollector<T>)
}
Flow
interface Flow<out T> {
suspend fun collect(collector: FlowCollector<T>)
}
interface FlowCollector<in T> {
suspend fun emit(value: T)
}
Builders
// From fixed set of values
val flowA = flowOf(1, 2, 3)
// From function type () -> T
val flowB = { repeat(3) { it + 1 } }.asFlow()
// Sequential call to the emit() function
val flowC = flow {
emit(1)
emit(2)
emit(3)
}
fun <T> Iterator<T>.asFlow(): Flow<T>
fun <T> Iterable<T>.asFlow(): Flow<T>
fun <T> emptyFlow(): Flow<T>
fun <T> Array<T>.asFlow(): Flow<T>
fun IntRange.asFlow(): Flow<Int>
fun <T> Sequence<T>.asFlow(): Flow<T>
fun <T> (() -> T).asFlow(): Flow<T>
fun <T> flow(
block: suspend FlowCollector<T>.() -> Unit
): Flow<T>
Builders
• map / mapNotNull

• switchMap

• combineLatest

• debounce / sample

• delayEach / delayFlow

• Zlter / ZlterNot / ZlterIsInstance / ZlterNotNull

• zip

• catch

• onEach / onCompletion

• atMapConcat / atMapMerge

• a]enConcat / a]enMerge
Intermediate

Operators
* Full list of available operators can be found in official documentation kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/-flow/
• collect

• single / Zrst

• toList / toSet / toCollection

• count

• fold / reduce

• launchIn / produceIn / broadcastIn
Terminal
Operators
Custom Operator
Built-in

Operators
interface Flow<out T> {
suspend fun collect(collector: FlowCollector<T>)
}
// Extension-oriented design approach
fun <T, R> Flow<T>.map(
transform: suspend (value: T) -> R
): Flow<R>
Custom

Operator
fun <T : Number> Flow<T>.sqrts(): Flow<Double> {
return flow { // this: FlowCollector<Double>
collect { number ->
val value = sqrt(number.toDouble())
emit(value)
}
}
}
Custom

Operator
fun <T : Number> Flow<T>.sqrts(): Flow<Double> {
return flow { // this: FlowCollector<Double>
collect { number ->
val value = sqrt(number.toDouble())
emit(value)
}
}
}
GlobalScope.launch {
flowOf(1, 2, 3)
.map { sqrt(it.toDouble()) }
.sqrts()
.collect()
}
Custom

Operator
fun <T : Number> Flow<T>.sqrts(): Flow<Double> {
return flow { // this: FlowCollector<Double>
collect { number ->
val value = sqrt(number.toDouble())
emit(value)
}
}
}
GlobalScope.launch {
flowOf(1, 2, 3)
.map { sqrt(it.toDouble()) }
.sqrts()
.collect()
}
Concurrent Flow
emi]er
collector
emi]er
collector
emi]er
collector
Coroutine A
Coroutine B
Concurrent Flow
fun <T> Flow<T>.buffer(
capacity: Int = Channel.UNLIMITED
): Flow<T> = flow {
val channel = coroutineScope.produce(capacity) {
collect { send(it) }
}
channel.consumeEach { emit(it) }
}
Concurrent Flow
fun <T> Flow<T>.buffer(capacity: Int): Flow<T>
fun <T> Flow<T>.produceIn(
scope: CoroutineScope
): ReceiveChannel<T>
fun <T> Flow<T>.broadcastIn(
scope: CoroutineScope,
start: CoroutineStart = CoroutineStart.LAZY
): BroadcastChannel<T>
fun <T> channelFlow(
block: suspend ProducerScope<T>.() -> Unit
): Flow<T>
Flow Constraints
• Context preservation

Flow encapsulates its own execution context and never propagates or leaks it
downstream
Flow Constraints
Context

Preservation
flow {
withContext(Dispatchers.Default) {
emit(longComputation())
}
}
Context

Preservation
flow {
withContext(Dispatchers.Default) {
emit(longComputation())
}
}
java.lang.IllegalStateException: Flow invariant is violated: flow was collected in
[Context A info], but emission happened in [Context B info]. Please refer to
'flow' documentation or use 'flowOn' instead
Context

Preservation
flow { emit(longComputation()) }
.flowOn(Dispatchers.Default)
Context

Preservation
flow {
GlobalScope.launch(Dispatchers.IO) // is prohibited
withContext(Dispatchers.Default) // is prohibited
emit(1) // OK
coroutineScope {

emit(2) // OK -- still the same coroutine

}
}
• Context preservation

Flow encapsulates its own execution context and never propagates or leaks it
downstream
• Exception transparency

Flow implementations never catch or handle exceptions that occur in
downstream <ows
Flow Constraints
flow<Any> {
try {
emitValue()
} catch (e: Exception) {
println("Error handled $e")
}
}
.map { process1() }
.collect { process2() }
Exception

Transparency
flow<Any> { emitValue() }
.map { process1() }
// catches exceptions in emitValue() and process1()
.catch { e -> println("Error handled $e") }
// throws exceptions from process2()
.collect { process2() }
Exception

Transparency
Old ways adapter
interface Stream<D> {
fun subscribe(callback: Callback<D>)
fun unsubscribe(callback: Callback<D>)
}
interface Callback<D> {
fun onNext(item: D)
fun onError(error: Throwable)
fun onCompleted()
}
Old ways adapter
val stream = Stream<Value>()
callbackFlow<Value> { // this: ProducerScope<Value>
// ProducerScope<Value> extends SendChannel<Value>
val callback = object : Callback<Value> {
override fun onNext(item: Value) { offer(item) }
override fun onError(error: Throwable) { close(error) }
override fun onCompleted() { close() }
}
stream.subscribe(callback)
awaitClose { stream.unsubscribe(callback) }
}
Old ways adapter
Reactive Streams
RxJava Operator
fun <T> Observable<T>.filter(
predicate: (T) -> Boolean
): Observable<T> = ObservableFilter(this, predicate)
RxJava Operator
class ObservableFilter<T>(
private val source: ObservableSource<T>,
private val predicate: (T) -> Boolean
) : Observable<T>(), HasUpstreamObservableSource<T> {
override fun source(): ObservableSource<T> = source
override fun subscribeActual(observer: Observer<in T>) {
source.subscribe(FilterObserver(observer, predicate))
}
internal class FilterObserver<T>(
actual: Observer<in T>,
private val filter: (T) -> Boolean
) : BasicFuseableObserver<T, T>(actual) {
override fun onNext(t: T) {
if (sourceMode == QueueFuseable.NONE) {
try {
if (filter(t)) downstream.onNext(t)
} catch (e: Throwable) {
fail(e)
}
} else {
downstream.onNext(null)
}
}
override fun requestFusion(mode: Int) = transitiveBoundaryFusion(mode)
override fun poll(): T? {
while (true) {
val v = qd.poll()
if (v == null || filter(v)) return v
}
}
}
}
fun <T> Observable<T>.filter(
predicate: (T) -> Boolean
): Observable<T> = ObservableFilter(this, predicate)
Flow Operator
fun <T> Flow<T>.filter(
predicate: suspend (T) -> Boolean
): Flow<T> {
return flow {
collect {
if (predicate(it)) emit(it)
}
}
}
Migration from
RxJava
RxJava 2 Coroutine
Single<T> Deferred<T> !❄
Maybe<T> Deferred<T?> !❄
Completable Job !❄
Observable<T>
Channel<T> !
Flow<T> ❄
Flowable<T>
fun <T> Observable<T>.toFlow(): Flow<T>
fun <T> Single<T>.toFlow(): Flow<T>
fun <T> Maybe<T>.toFlow(): Flow<T>
fun <T> Flowable<T>.toFlow(): Flow<T>
RxJava2 to Flow

Adapters
fun <T> Observable<T>.toFlow(): Flow<T>
fun <T> Single<T>.toFlow(): Flow<T>
fun <T> Maybe<T>.toFlow(): Flow<T>
fun <T> Flowable<T>.toFlow(): Flow<T>
NO FROM THE BOX :) WRITE YOU OWNRxJava2 to Flow

Adapters
Third-paNy library
integration
@Dao
interface SampleDao {
}
// Request data and observe changes with RxJava
@Query("SELECT * FROM ENTITIES")
fun queryEntities(): Observable<List<Entity>>Room
// Blocking request data
@Query("SELECT * FROM ENTITIES")
fun queryEntities(): List<Entity>
@Dao
interface SampleDao {
}
// Request data and observe changes with RxJava
@Query("SELECT * FROM ENTITIES")
fun queryEntities(): Observable<List<Entity>>Room
// Blocking request data
@Query("SELECT * FROM ENTITIES")
fun queryEntities(): List<Entity>
// Request data using Coroutines
@Query("SELECT * FROM ENTITIES")
suspend fun queryEntities(): List<Entity>
@Dao
interface SampleDao {
}
// Request data and observe changes with RxJava
@Query("SELECT * FROM ENTITIES")
fun queryEntities(): Observable<List<Entity>>Room
// Blocking request data
@Query("SELECT * FROM ENTITIES")
fun queryEntities(): List<Entity>
// Request data using Coroutines
@Query("SELECT * FROM ENTITIES")
suspend fun queryEntities(): List<Entity>
// Request data and observe changes using Coroutines
@Query("SELECT * FROM ENTITIES")
fun queryEntities(): Flow<List<Entity>>
val database = getSampleDatabase()
GlobalScope.launch {
database.sampleDao.queryEntities().collect {
// Handle updates of entities
}
}
Room
interface GitHubService {
}
RetroZt
@GET("users/{user}/repos")
fun listRepos(
@Path("user") user: String
): Call<List<Repo>>
interface GitHubService {
}
RetroZt
@GET("users/{user}/repos")
suspend fun listRepos(
@Path("user") user: String
): List<Repo>
@GET("users/{user}/repos")
fun listRepos(
@Path("user") user: String
): Call<List<Repo>>
interface GitHubService {
}
RetroZt
@GET("users/{user}/repos")
suspend fun listRepos(
@Path("user") user: String
): List<Repo>
@GET("users/{user}/repos")
fun listRepos(
@Path("user") user: String
): Flow<List<Repo>>
@GET("users/{user}/repos")
fun listRepos(
@Path("user") user: String
): Call<List<Repo>>
fun <T> Call<T>.asFlow(): Flow<T> = callbackFlow {
enqueue(object : Callback<T> {
override fun onFailure(call: Call<T>, error: Throwable) {
close(error)
}
override fun onResponse(call: Call<T>, response: Response<T>) {
if (response.isSuccessful) {
offer(response.body()!!)
close()
} else {
close(RetrofitError(response.errorBody()))
}
}
})
awaitClose {
if (!isCanceled) {
cancel()
}
}
}
class RetrofitError(val errorBody: ResponseBody?) : Throwable()
RetroZt
val service = getGitHubService()
GlobalScope.launch {
service.listRepos("user-id")
.asFlow()
.collect {
// handle response
}
}
RetroZt
• Flow will be primary way to handle async stream
of data

• Channels will be used:

• for hot streams

• “under-the-hood” in some Flow operators

• as synchronization primitive between
Coroutines
What will be the
next?
Thank you!
krl.rozov@gmail.com
@android_broadcast
@kirill_rozov

More Related Content

What's hot

Introduction to Kotlin coroutines
Introduction to Kotlin coroutinesIntroduction to Kotlin coroutines
Introduction to Kotlin coroutines
Roman Elizarov
 
Blazing Fast, Pure Effects without Monads — LambdaConf 2018
Blazing Fast, Pure Effects without Monads — LambdaConf 2018Blazing Fast, Pure Effects without Monads — LambdaConf 2018
Blazing Fast, Pure Effects without Monads — LambdaConf 2018
John De Goes
 
Threading Made Easy! A Busy Developer’s Guide to Kotlin Coroutines
Threading Made Easy! A Busy Developer’s Guide to Kotlin CoroutinesThreading Made Easy! A Busy Developer’s Guide to Kotlin Coroutines
Threading Made Easy! A Busy Developer’s Guide to Kotlin Coroutines
Lauren Yew
 
Android kotlin coroutines
Android kotlin coroutinesAndroid kotlin coroutines
Android kotlin coroutines
Bipin Vayalu
 
Gor Nishanov, C++ Coroutines – a negative overhead abstraction
Gor Nishanov,  C++ Coroutines – a negative overhead abstractionGor Nishanov,  C++ Coroutines – a negative overhead abstraction
Gor Nishanov, C++ Coroutines – a negative overhead abstraction
Sergey Platonov
 
Functor, Apply, Applicative And Monad
Functor, Apply, Applicative And MonadFunctor, Apply, Applicative And Monad
Functor, Apply, Applicative And Monad
Oliver Daff
 
Error Management: Future vs ZIO
Error Management: Future vs ZIOError Management: Future vs ZIO
Error Management: Future vs ZIO
John De Goes
 
Taking your side effects aside
Taking your side effects asideTaking your side effects aside
Taking your side effects aside
💡 Tomasz Kogut
 
Kotlin
KotlinKotlin
Kotlin
Rory Preddy
 
A Prelude of Purity: Scaling Back ZIO
A Prelude of Purity: Scaling Back ZIOA Prelude of Purity: Scaling Back ZIO
A Prelude of Purity: Scaling Back ZIO
Jorge Vásquez
 
Kotlin - Better Java
Kotlin - Better JavaKotlin - Better Java
Kotlin - Better Java
Dariusz Lorenc
 
Jetpack Compose - Android’s modern toolkit for building native UI
Jetpack Compose - Android’s modern toolkit for building native UIJetpack Compose - Android’s modern toolkit for building native UI
Jetpack Compose - Android’s modern toolkit for building native UI
Gilang Ramadhan
 
Kotlin - scope functions and collections
Kotlin - scope functions and collectionsKotlin - scope functions and collections
Kotlin - scope functions and collections
Wei-Shen Lu
 
Redux Sagas - React Alicante
Redux Sagas - React AlicanteRedux Sagas - React Alicante
Redux Sagas - React Alicante
Ignacio Martín
 
Functional Programming 101 with Scala and ZIO @FunctionalWorld
Functional Programming 101 with Scala and ZIO @FunctionalWorldFunctional Programming 101 with Scala and ZIO @FunctionalWorld
Functional Programming 101 with Scala and ZIO @FunctionalWorld
Jorge Vásquez
 
Coroutines in Kotlin. In-depth review
Coroutines in Kotlin. In-depth reviewCoroutines in Kotlin. In-depth review
Coroutines in Kotlin. In-depth review
Dmytro Zaitsev
 
Kotlin Coroutines and Android sitting in a tree
Kotlin Coroutines and Android sitting in a treeKotlin Coroutines and Android sitting in a tree
Kotlin Coroutines and Android sitting in a tree
Kai Koenig
 
Domain Modeling with FP (DDD Europe 2020)
Domain Modeling with FP (DDD Europe 2020)Domain Modeling with FP (DDD Europe 2020)
Domain Modeling with FP (DDD Europe 2020)
Scott Wlaschin
 
Android Jetpack Compose - Turkey 2021
Android Jetpack Compose - Turkey 2021Android Jetpack Compose - Turkey 2021
Android Jetpack Compose - Turkey 2021
Nelson Glauber Leal
 
Monoids - Part 1 - with examples using Scalaz and Cats
Monoids - Part 1 - with examples using Scalaz and CatsMonoids - Part 1 - with examples using Scalaz and Cats
Monoids - Part 1 - with examples using Scalaz and Cats
Philip Schwarz
 

What's hot (20)

Introduction to Kotlin coroutines
Introduction to Kotlin coroutinesIntroduction to Kotlin coroutines
Introduction to Kotlin coroutines
 
Blazing Fast, Pure Effects without Monads — LambdaConf 2018
Blazing Fast, Pure Effects without Monads — LambdaConf 2018Blazing Fast, Pure Effects without Monads — LambdaConf 2018
Blazing Fast, Pure Effects without Monads — LambdaConf 2018
 
Threading Made Easy! A Busy Developer’s Guide to Kotlin Coroutines
Threading Made Easy! A Busy Developer’s Guide to Kotlin CoroutinesThreading Made Easy! A Busy Developer’s Guide to Kotlin Coroutines
Threading Made Easy! A Busy Developer’s Guide to Kotlin Coroutines
 
Android kotlin coroutines
Android kotlin coroutinesAndroid kotlin coroutines
Android kotlin coroutines
 
Gor Nishanov, C++ Coroutines – a negative overhead abstraction
Gor Nishanov,  C++ Coroutines – a negative overhead abstractionGor Nishanov,  C++ Coroutines – a negative overhead abstraction
Gor Nishanov, C++ Coroutines – a negative overhead abstraction
 
Functor, Apply, Applicative And Monad
Functor, Apply, Applicative And MonadFunctor, Apply, Applicative And Monad
Functor, Apply, Applicative And Monad
 
Error Management: Future vs ZIO
Error Management: Future vs ZIOError Management: Future vs ZIO
Error Management: Future vs ZIO
 
Taking your side effects aside
Taking your side effects asideTaking your side effects aside
Taking your side effects aside
 
Kotlin
KotlinKotlin
Kotlin
 
A Prelude of Purity: Scaling Back ZIO
A Prelude of Purity: Scaling Back ZIOA Prelude of Purity: Scaling Back ZIO
A Prelude of Purity: Scaling Back ZIO
 
Kotlin - Better Java
Kotlin - Better JavaKotlin - Better Java
Kotlin - Better Java
 
Jetpack Compose - Android’s modern toolkit for building native UI
Jetpack Compose - Android’s modern toolkit for building native UIJetpack Compose - Android’s modern toolkit for building native UI
Jetpack Compose - Android’s modern toolkit for building native UI
 
Kotlin - scope functions and collections
Kotlin - scope functions and collectionsKotlin - scope functions and collections
Kotlin - scope functions and collections
 
Redux Sagas - React Alicante
Redux Sagas - React AlicanteRedux Sagas - React Alicante
Redux Sagas - React Alicante
 
Functional Programming 101 with Scala and ZIO @FunctionalWorld
Functional Programming 101 with Scala and ZIO @FunctionalWorldFunctional Programming 101 with Scala and ZIO @FunctionalWorld
Functional Programming 101 with Scala and ZIO @FunctionalWorld
 
Coroutines in Kotlin. In-depth review
Coroutines in Kotlin. In-depth reviewCoroutines in Kotlin. In-depth review
Coroutines in Kotlin. In-depth review
 
Kotlin Coroutines and Android sitting in a tree
Kotlin Coroutines and Android sitting in a treeKotlin Coroutines and Android sitting in a tree
Kotlin Coroutines and Android sitting in a tree
 
Domain Modeling with FP (DDD Europe 2020)
Domain Modeling with FP (DDD Europe 2020)Domain Modeling with FP (DDD Europe 2020)
Domain Modeling with FP (DDD Europe 2020)
 
Android Jetpack Compose - Turkey 2021
Android Jetpack Compose - Turkey 2021Android Jetpack Compose - Turkey 2021
Android Jetpack Compose - Turkey 2021
 
Monoids - Part 1 - with examples using Scalaz and Cats
Monoids - Part 1 - with examples using Scalaz and CatsMonoids - Part 1 - with examples using Scalaz and Cats
Monoids - Part 1 - with examples using Scalaz and Cats
 

Similar to Kotlin Coroutines. Flow is coming

Практическое применения Akka Streams
Практическое применения Akka StreamsПрактическое применения Akka Streams
Практическое применения Akka Streams
Alexey Romanchuk
 
«Практическое применение Akka Streams» — Алексей Романчук, 2ГИС
«Практическое применение Akka Streams» — Алексей Романчук, 2ГИС«Практическое применение Akka Streams» — Алексей Романчук, 2ГИС
«Практическое применение Akka Streams» — Алексей Романчук, 2ГИС
2ГИС Технологии
 
Coroutines in Kotlin. UA Mobile 2017.
Coroutines in Kotlin. UA Mobile 2017.Coroutines in Kotlin. UA Mobile 2017.
Coroutines in Kotlin. UA Mobile 2017.
UA Mobile
 
Generating and Analyzing Events
Generating and Analyzing EventsGenerating and Analyzing Events
Generating and Analyzing Events
ztellman
 
Operation Flow @ ChicagoRoboto
Operation Flow @ ChicagoRobotoOperation Flow @ ChicagoRoboto
Operation Flow @ ChicagoRoboto
Seyed Jafari
 
Creating Lazy stream in CSharp
Creating Lazy stream in CSharpCreating Lazy stream in CSharp
Creating Lazy stream in CSharp
Dhaval Dalal
 
Dive into kotlins coroutines
Dive into kotlins coroutinesDive into kotlins coroutines
Dive into kotlins coroutines
Freddie Wang
 
Job Queue in Golang
Job Queue in GolangJob Queue in Golang
Job Queue in Golang
Bo-Yi Wu
 
Goroutines and Channels in practice
Goroutines and Channels in practiceGoroutines and Channels in practice
Goroutines and Channels in practice
Guilherme Garnier
 
Current State of Coroutines
Current State of CoroutinesCurrent State of Coroutines
Current State of Coroutines
Guido Pio Mariotti
 
Fs2 - Crash Course
Fs2 - Crash CourseFs2 - Crash Course
Fs2 - Crash Course
Lukasz Byczynski
 
Dip into Coroutines - KTUG Munich 202303
Dip into Coroutines - KTUG Munich 202303Dip into Coroutines - KTUG Munich 202303
Dip into Coroutines - KTUG Munich 202303
Alex Semin
 
Mastering Kotlin Standard Library
Mastering Kotlin Standard LibraryMastering Kotlin Standard Library
Mastering Kotlin Standard Library
Nelson Glauber Leal
 
Lego: A brick system build by scala
Lego: A brick system build by scalaLego: A brick system build by scala
Lego: A brick system build by scalalunfu zhong
 
Csp scala wixmeetup2016
Csp scala wixmeetup2016Csp scala wixmeetup2016
Csp scala wixmeetup2016
Ruslan Shevchenko
 
Akka.NET streams and reactive streams
Akka.NET streams and reactive streamsAkka.NET streams and reactive streams
Akka.NET streams and reactive streams
Bartosz Sypytkowski
 
Scala-Gopher: CSP-style programming techniques with idiomatic Scala.
Scala-Gopher: CSP-style programming techniques with idiomatic Scala.Scala-Gopher: CSP-style programming techniques with idiomatic Scala.
Scala-Gopher: CSP-style programming techniques with idiomatic Scala.
Ruslan Shevchenko
 
Designing for Distributed Systems with Reactor and Reactive Streams
Designing for Distributed Systems with Reactor and Reactive StreamsDesigning for Distributed Systems with Reactor and Reactive Streams
Designing for Distributed Systems with Reactor and Reactive Streams
Stéphane Maldini
 
CROCHET - Checkpoint Rollback in JVM (ECOOP 2018)
CROCHET - Checkpoint Rollback in JVM (ECOOP 2018)CROCHET - Checkpoint Rollback in JVM (ECOOP 2018)
CROCHET - Checkpoint Rollback in JVM (ECOOP 2018)
jon_bell
 
Reactive programming on Android
Reactive programming on AndroidReactive programming on Android
Reactive programming on Android
Tomáš Kypta
 

Similar to Kotlin Coroutines. Flow is coming (20)

Практическое применения Akka Streams
Практическое применения Akka StreamsПрактическое применения Akka Streams
Практическое применения Akka Streams
 
«Практическое применение Akka Streams» — Алексей Романчук, 2ГИС
«Практическое применение Akka Streams» — Алексей Романчук, 2ГИС«Практическое применение Akka Streams» — Алексей Романчук, 2ГИС
«Практическое применение Akka Streams» — Алексей Романчук, 2ГИС
 
Coroutines in Kotlin. UA Mobile 2017.
Coroutines in Kotlin. UA Mobile 2017.Coroutines in Kotlin. UA Mobile 2017.
Coroutines in Kotlin. UA Mobile 2017.
 
Generating and Analyzing Events
Generating and Analyzing EventsGenerating and Analyzing Events
Generating and Analyzing Events
 
Operation Flow @ ChicagoRoboto
Operation Flow @ ChicagoRobotoOperation Flow @ ChicagoRoboto
Operation Flow @ ChicagoRoboto
 
Creating Lazy stream in CSharp
Creating Lazy stream in CSharpCreating Lazy stream in CSharp
Creating Lazy stream in CSharp
 
Dive into kotlins coroutines
Dive into kotlins coroutinesDive into kotlins coroutines
Dive into kotlins coroutines
 
Job Queue in Golang
Job Queue in GolangJob Queue in Golang
Job Queue in Golang
 
Goroutines and Channels in practice
Goroutines and Channels in practiceGoroutines and Channels in practice
Goroutines and Channels in practice
 
Current State of Coroutines
Current State of CoroutinesCurrent State of Coroutines
Current State of Coroutines
 
Fs2 - Crash Course
Fs2 - Crash CourseFs2 - Crash Course
Fs2 - Crash Course
 
Dip into Coroutines - KTUG Munich 202303
Dip into Coroutines - KTUG Munich 202303Dip into Coroutines - KTUG Munich 202303
Dip into Coroutines - KTUG Munich 202303
 
Mastering Kotlin Standard Library
Mastering Kotlin Standard LibraryMastering Kotlin Standard Library
Mastering Kotlin Standard Library
 
Lego: A brick system build by scala
Lego: A brick system build by scalaLego: A brick system build by scala
Lego: A brick system build by scala
 
Csp scala wixmeetup2016
Csp scala wixmeetup2016Csp scala wixmeetup2016
Csp scala wixmeetup2016
 
Akka.NET streams and reactive streams
Akka.NET streams and reactive streamsAkka.NET streams and reactive streams
Akka.NET streams and reactive streams
 
Scala-Gopher: CSP-style programming techniques with idiomatic Scala.
Scala-Gopher: CSP-style programming techniques with idiomatic Scala.Scala-Gopher: CSP-style programming techniques with idiomatic Scala.
Scala-Gopher: CSP-style programming techniques with idiomatic Scala.
 
Designing for Distributed Systems with Reactor and Reactive Streams
Designing for Distributed Systems with Reactor and Reactive StreamsDesigning for Distributed Systems with Reactor and Reactive Streams
Designing for Distributed Systems with Reactor and Reactive Streams
 
CROCHET - Checkpoint Rollback in JVM (ECOOP 2018)
CROCHET - Checkpoint Rollback in JVM (ECOOP 2018)CROCHET - Checkpoint Rollback in JVM (ECOOP 2018)
CROCHET - Checkpoint Rollback in JVM (ECOOP 2018)
 
Reactive programming on Android
Reactive programming on AndroidReactive programming on Android
Reactive programming on Android
 

More from Kirill Rozov

2 years without Java. Kotlin only
2 years without Java. Kotlin only2 years without Java. Kotlin only
2 years without Java. Kotlin only
Kirill Rozov
 
Почему Kotlin?
Почему Kotlin?Почему Kotlin?
Почему Kotlin?
Kirill Rozov
 
KOIN for dependency Injection
KOIN for dependency InjectionKOIN for dependency Injection
KOIN for dependency Injection
Kirill Rozov
 
Optimize APK size
Optimize APK sizeOptimize APK size
Optimize APK size
Kirill Rozov
 
ConstraintLayout. Fell the Power of constraints
ConstraintLayout. Fell the Power of constraintsConstraintLayout. Fell the Power of constraints
ConstraintLayout. Fell the Power of constraints
Kirill Rozov
 
Kotlin 1.2: Sharing code between platforms
Kotlin 1.2: Sharing code between platformsKotlin 1.2: Sharing code between platforms
Kotlin 1.2: Sharing code between platforms
Kirill Rozov
 
Kotlin - следующий язык после Java
Kotlin - следующий язык после JavaKotlin - следующий язык после Java
Kotlin - следующий язык после Java
Kirill Rozov
 
Kotlin Advanced - Apalon Kotlin Sprint Part 3
Kotlin Advanced - Apalon Kotlin Sprint Part 3Kotlin Advanced - Apalon Kotlin Sprint Part 3
Kotlin Advanced - Apalon Kotlin Sprint Part 3
Kirill Rozov
 
Kotlin Basics - Apalon Kotlin Sprint Part 2
Kotlin Basics - Apalon Kotlin Sprint Part 2Kotlin Basics - Apalon Kotlin Sprint Part 2
Kotlin Basics - Apalon Kotlin Sprint Part 2
Kirill Rozov
 
Why Kotlin - Apalon Kotlin Sprint Part 1
Why Kotlin - Apalon Kotlin Sprint Part 1Why Kotlin - Apalon Kotlin Sprint Part 1
Why Kotlin - Apalon Kotlin Sprint Part 1
Kirill Rozov
 
Тестирование на Android с Dagger 2
Тестирование на Android с Dagger 2Тестирование на Android с Dagger 2
Тестирование на Android с Dagger 2
Kirill Rozov
 
Что нового в Android O (Grodno HTP)
Что нового в Android O (Grodno HTP)Что нового в Android O (Grodno HTP)
Что нового в Android O (Grodno HTP)
Kirill Rozov
 
What's new in Android O
What's new in Android OWhat's new in Android O
What's new in Android O
Kirill Rozov
 
Android service
Android serviceAndroid service
Android service
Kirill Rozov
 
Effective Java
Effective JavaEffective Java
Effective Java
Kirill Rozov
 
Dagger 2
Dagger 2Dagger 2
Dagger 2
Kirill Rozov
 
Gradle Introduction
Gradle IntroductionGradle Introduction
Gradle Introduction
Kirill Rozov
 
REST
RESTREST
Kotlin для Android
Kotlin для AndroidKotlin для Android
Kotlin для Android
Kirill Rozov
 
What's new in Android M
What's new in Android MWhat's new in Android M
What's new in Android M
Kirill Rozov
 

More from Kirill Rozov (20)

2 years without Java. Kotlin only
2 years without Java. Kotlin only2 years without Java. Kotlin only
2 years without Java. Kotlin only
 
Почему Kotlin?
Почему Kotlin?Почему Kotlin?
Почему Kotlin?
 
KOIN for dependency Injection
KOIN for dependency InjectionKOIN for dependency Injection
KOIN for dependency Injection
 
Optimize APK size
Optimize APK sizeOptimize APK size
Optimize APK size
 
ConstraintLayout. Fell the Power of constraints
ConstraintLayout. Fell the Power of constraintsConstraintLayout. Fell the Power of constraints
ConstraintLayout. Fell the Power of constraints
 
Kotlin 1.2: Sharing code between platforms
Kotlin 1.2: Sharing code between platformsKotlin 1.2: Sharing code between platforms
Kotlin 1.2: Sharing code between platforms
 
Kotlin - следующий язык после Java
Kotlin - следующий язык после JavaKotlin - следующий язык после Java
Kotlin - следующий язык после Java
 
Kotlin Advanced - Apalon Kotlin Sprint Part 3
Kotlin Advanced - Apalon Kotlin Sprint Part 3Kotlin Advanced - Apalon Kotlin Sprint Part 3
Kotlin Advanced - Apalon Kotlin Sprint Part 3
 
Kotlin Basics - Apalon Kotlin Sprint Part 2
Kotlin Basics - Apalon Kotlin Sprint Part 2Kotlin Basics - Apalon Kotlin Sprint Part 2
Kotlin Basics - Apalon Kotlin Sprint Part 2
 
Why Kotlin - Apalon Kotlin Sprint Part 1
Why Kotlin - Apalon Kotlin Sprint Part 1Why Kotlin - Apalon Kotlin Sprint Part 1
Why Kotlin - Apalon Kotlin Sprint Part 1
 
Тестирование на Android с Dagger 2
Тестирование на Android с Dagger 2Тестирование на Android с Dagger 2
Тестирование на Android с Dagger 2
 
Что нового в Android O (Grodno HTP)
Что нового в Android O (Grodno HTP)Что нового в Android O (Grodno HTP)
Что нового в Android O (Grodno HTP)
 
What's new in Android O
What's new in Android OWhat's new in Android O
What's new in Android O
 
Android service
Android serviceAndroid service
Android service
 
Effective Java
Effective JavaEffective Java
Effective Java
 
Dagger 2
Dagger 2Dagger 2
Dagger 2
 
Gradle Introduction
Gradle IntroductionGradle Introduction
Gradle Introduction
 
REST
RESTREST
REST
 
Kotlin для Android
Kotlin для AndroidKotlin для Android
Kotlin для Android
 
What's new in Android M
What's new in Android MWhat's new in Android M
What's new in Android M
 

Recently uploaded

The Benefits and Techniques of Trenchless Pipe Repair.pdf
The Benefits and Techniques of Trenchless Pipe Repair.pdfThe Benefits and Techniques of Trenchless Pipe Repair.pdf
The Benefits and Techniques of Trenchless Pipe Repair.pdf
Pipe Restoration Solutions
 
Design and Analysis of Algorithms-DP,Backtracking,Graphs,B&B
Design and Analysis of Algorithms-DP,Backtracking,Graphs,B&BDesign and Analysis of Algorithms-DP,Backtracking,Graphs,B&B
Design and Analysis of Algorithms-DP,Backtracking,Graphs,B&B
Sreedhar Chowdam
 
Courier management system project report.pdf
Courier management system project report.pdfCourier management system project report.pdf
Courier management system project report.pdf
Kamal Acharya
 
HYDROPOWER - Hydroelectric power generation
HYDROPOWER - Hydroelectric power generationHYDROPOWER - Hydroelectric power generation
HYDROPOWER - Hydroelectric power generation
Robbie Edward Sayers
 
Immunizing Image Classifiers Against Localized Adversary Attacks
Immunizing Image Classifiers Against Localized Adversary AttacksImmunizing Image Classifiers Against Localized Adversary Attacks
Immunizing Image Classifiers Against Localized Adversary Attacks
gerogepatton
 
Gen AI Study Jams _ For the GDSC Leads in India.pdf
Gen AI Study Jams _ For the GDSC Leads in India.pdfGen AI Study Jams _ For the GDSC Leads in India.pdf
Gen AI Study Jams _ For the GDSC Leads in India.pdf
gdsczhcet
 
MCQ Soil mechanics questions (Soil shear strength).pdf
MCQ Soil mechanics questions (Soil shear strength).pdfMCQ Soil mechanics questions (Soil shear strength).pdf
MCQ Soil mechanics questions (Soil shear strength).pdf
Osamah Alsalih
 
Planning Of Procurement o different goods and services
Planning Of Procurement o different goods and servicesPlanning Of Procurement o different goods and services
Planning Of Procurement o different goods and services
JoytuBarua2
 
LIGA(E)11111111111111111111111111111111111111111.ppt
LIGA(E)11111111111111111111111111111111111111111.pptLIGA(E)11111111111111111111111111111111111111111.ppt
LIGA(E)11111111111111111111111111111111111111111.ppt
ssuser9bd3ba
 
addressing modes in computer architecture
addressing modes  in computer architectureaddressing modes  in computer architecture
addressing modes in computer architecture
ShahidSultan24
 
Nuclear Power Economics and Structuring 2024
Nuclear Power Economics and Structuring 2024Nuclear Power Economics and Structuring 2024
Nuclear Power Economics and Structuring 2024
Massimo Talia
 
The role of big data in decision making.
The role of big data in decision making.The role of big data in decision making.
The role of big data in decision making.
ankuprajapati0525
 
在线办理(ANU毕业证书)澳洲国立大学毕业证录取通知书一模一样
在线办理(ANU毕业证书)澳洲国立大学毕业证录取通知书一模一样在线办理(ANU毕业证书)澳洲国立大学毕业证录取通知书一模一样
在线办理(ANU毕业证书)澳洲国立大学毕业证录取通知书一模一样
obonagu
 
Sachpazis:Terzaghi Bearing Capacity Estimation in simple terms with Calculati...
Sachpazis:Terzaghi Bearing Capacity Estimation in simple terms with Calculati...Sachpazis:Terzaghi Bearing Capacity Estimation in simple terms with Calculati...
Sachpazis:Terzaghi Bearing Capacity Estimation in simple terms with Calculati...
Dr.Costas Sachpazis
 
Standard Reomte Control Interface - Neometrix
Standard Reomte Control Interface - NeometrixStandard Reomte Control Interface - Neometrix
Standard Reomte Control Interface - Neometrix
Neometrix_Engineering_Pvt_Ltd
 
Halogenation process of chemical process industries
Halogenation process of chemical process industriesHalogenation process of chemical process industries
Halogenation process of chemical process industries
MuhammadTufail242431
 
Final project report on grocery store management system..pdf
Final project report on grocery store management system..pdfFinal project report on grocery store management system..pdf
Final project report on grocery store management system..pdf
Kamal Acharya
 
Democratizing Fuzzing at Scale by Abhishek Arya
Democratizing Fuzzing at Scale by Abhishek AryaDemocratizing Fuzzing at Scale by Abhishek Arya
Democratizing Fuzzing at Scale by Abhishek Arya
abh.arya
 
Student information management system project report ii.pdf
Student information management system project report ii.pdfStudent information management system project report ii.pdf
Student information management system project report ii.pdf
Kamal Acharya
 
Quality defects in TMT Bars, Possible causes and Potential Solutions.
Quality defects in TMT Bars, Possible causes and Potential Solutions.Quality defects in TMT Bars, Possible causes and Potential Solutions.
Quality defects in TMT Bars, Possible causes and Potential Solutions.
PrashantGoswami42
 

Recently uploaded (20)

The Benefits and Techniques of Trenchless Pipe Repair.pdf
The Benefits and Techniques of Trenchless Pipe Repair.pdfThe Benefits and Techniques of Trenchless Pipe Repair.pdf
The Benefits and Techniques of Trenchless Pipe Repair.pdf
 
Design and Analysis of Algorithms-DP,Backtracking,Graphs,B&B
Design and Analysis of Algorithms-DP,Backtracking,Graphs,B&BDesign and Analysis of Algorithms-DP,Backtracking,Graphs,B&B
Design and Analysis of Algorithms-DP,Backtracking,Graphs,B&B
 
Courier management system project report.pdf
Courier management system project report.pdfCourier management system project report.pdf
Courier management system project report.pdf
 
HYDROPOWER - Hydroelectric power generation
HYDROPOWER - Hydroelectric power generationHYDROPOWER - Hydroelectric power generation
HYDROPOWER - Hydroelectric power generation
 
Immunizing Image Classifiers Against Localized Adversary Attacks
Immunizing Image Classifiers Against Localized Adversary AttacksImmunizing Image Classifiers Against Localized Adversary Attacks
Immunizing Image Classifiers Against Localized Adversary Attacks
 
Gen AI Study Jams _ For the GDSC Leads in India.pdf
Gen AI Study Jams _ For the GDSC Leads in India.pdfGen AI Study Jams _ For the GDSC Leads in India.pdf
Gen AI Study Jams _ For the GDSC Leads in India.pdf
 
MCQ Soil mechanics questions (Soil shear strength).pdf
MCQ Soil mechanics questions (Soil shear strength).pdfMCQ Soil mechanics questions (Soil shear strength).pdf
MCQ Soil mechanics questions (Soil shear strength).pdf
 
Planning Of Procurement o different goods and services
Planning Of Procurement o different goods and servicesPlanning Of Procurement o different goods and services
Planning Of Procurement o different goods and services
 
LIGA(E)11111111111111111111111111111111111111111.ppt
LIGA(E)11111111111111111111111111111111111111111.pptLIGA(E)11111111111111111111111111111111111111111.ppt
LIGA(E)11111111111111111111111111111111111111111.ppt
 
addressing modes in computer architecture
addressing modes  in computer architectureaddressing modes  in computer architecture
addressing modes in computer architecture
 
Nuclear Power Economics and Structuring 2024
Nuclear Power Economics and Structuring 2024Nuclear Power Economics and Structuring 2024
Nuclear Power Economics and Structuring 2024
 
The role of big data in decision making.
The role of big data in decision making.The role of big data in decision making.
The role of big data in decision making.
 
在线办理(ANU毕业证书)澳洲国立大学毕业证录取通知书一模一样
在线办理(ANU毕业证书)澳洲国立大学毕业证录取通知书一模一样在线办理(ANU毕业证书)澳洲国立大学毕业证录取通知书一模一样
在线办理(ANU毕业证书)澳洲国立大学毕业证录取通知书一模一样
 
Sachpazis:Terzaghi Bearing Capacity Estimation in simple terms with Calculati...
Sachpazis:Terzaghi Bearing Capacity Estimation in simple terms with Calculati...Sachpazis:Terzaghi Bearing Capacity Estimation in simple terms with Calculati...
Sachpazis:Terzaghi Bearing Capacity Estimation in simple terms with Calculati...
 
Standard Reomte Control Interface - Neometrix
Standard Reomte Control Interface - NeometrixStandard Reomte Control Interface - Neometrix
Standard Reomte Control Interface - Neometrix
 
Halogenation process of chemical process industries
Halogenation process of chemical process industriesHalogenation process of chemical process industries
Halogenation process of chemical process industries
 
Final project report on grocery store management system..pdf
Final project report on grocery store management system..pdfFinal project report on grocery store management system..pdf
Final project report on grocery store management system..pdf
 
Democratizing Fuzzing at Scale by Abhishek Arya
Democratizing Fuzzing at Scale by Abhishek AryaDemocratizing Fuzzing at Scale by Abhishek Arya
Democratizing Fuzzing at Scale by Abhishek Arya
 
Student information management system project report ii.pdf
Student information management system project report ii.pdfStudent information management system project report ii.pdf
Student information management system project report ii.pdf
 
Quality defects in TMT Bars, Possible causes and Potential Solutions.
Quality defects in TMT Bars, Possible causes and Potential Solutions.Quality defects in TMT Bars, Possible causes and Potential Solutions.
Quality defects in TMT Bars, Possible causes and Potential Solutions.
 

Kotlin Coroutines. Flow is coming

  • 4. 1. Channels 2. Flows 3. Custom operator 4. Concurrent Flow 5. Flow constraints 6. Adapter 7. Reactive Stream 8. Backpressure 9. Third paNy integrations Agenda
  • 5. Async in Kotlin // Single value suspend fun foo(p: Params): Value = withContext(Dispatchers.Default) { bar(p) } // Collection of values suspend fun foo(p: Params): List<Value> = buildList { while (hasMore) add(nextValue) } // Stream of values fun foo(p: Params): Sequence<Value> = sequence { while (hasMore) yield(nextValue) }
  • 6. Async in Kotlin // Single value suspend fun foo(p: Params): Value = withContext(Dispatchers.Default) { bar(p) } // Collection of values suspend fun foo(p: Params): List<Value> = buildList { while (hasMore) add(nextValue) } // Stream of values fun foo(p: Params): Sequence<Value> = sequence { while (hasMore) yield(nextValue) } Blocking
  • 8. Channels fun CoroutineScope.fooProducer(p: Params) : ReceiveChannel<Value> { return produce { while (hasMore) send(nextValue) } }
  • 9. Channels fun CoroutineScope.fooProducer(p: Params) : ReceiveChannel<Value> { return produce { while (hasMore) send(nextValue) } } val values: ReceiveChannel<Value> = fooProducer(p) if (someCondition) { return anotherResult // Oops! Leaked channel } // ... do further work with values ...
  • 10. • Works with data sources that are intrinsically hot
 Data sources that exist without application’s requests for them • incoming network connections • event streams • Synchronization primitives • For transfer data between coroutines • Synchronize access to the same data from multiply coroutines Channels
  • 11. Flows
  • 12. Flow is a cold asynchronous data stream that executed sequentially (in the same coroutine) emits values and completes normally or with an exception kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/-flow/
  • 13. GlobalScope.launch { flowOf(1, 2, 3) .map { it * it } .collect { print(it) } } Flow
  • 14. Flow interface Flow<out T> { suspend fun collect(collector: FlowCollector<T>) }
  • 15. Flow interface Flow<out T> { suspend fun collect(collector: FlowCollector<T>) } interface FlowCollector<in T> { suspend fun emit(value: T) }
  • 16. Builders // From fixed set of values val flowA = flowOf(1, 2, 3) // From function type () -> T val flowB = { repeat(3) { it + 1 } }.asFlow() // Sequential call to the emit() function val flowC = flow { emit(1) emit(2) emit(3) }
  • 17. fun <T> Iterator<T>.asFlow(): Flow<T> fun <T> Iterable<T>.asFlow(): Flow<T> fun <T> emptyFlow(): Flow<T> fun <T> Array<T>.asFlow(): Flow<T> fun IntRange.asFlow(): Flow<Int> fun <T> Sequence<T>.asFlow(): Flow<T> fun <T> (() -> T).asFlow(): Flow<T> fun <T> flow( block: suspend FlowCollector<T>.() -> Unit ): Flow<T> Builders
  • 18. • map / mapNotNull • switchMap • combineLatest • debounce / sample • delayEach / delayFlow • Zlter / ZlterNot / ZlterIsInstance / ZlterNotNull • zip • catch • onEach / onCompletion • atMapConcat / atMapMerge • a]enConcat / a]enMerge Intermediate
 Operators * Full list of available operators can be found in official documentation kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/-flow/
  • 19. • collect • single / Zrst • toList / toSet / toCollection • count • fold / reduce • launchIn / produceIn / broadcastIn Terminal Operators
  • 21. Built-in
 Operators interface Flow<out T> { suspend fun collect(collector: FlowCollector<T>) } // Extension-oriented design approach fun <T, R> Flow<T>.map( transform: suspend (value: T) -> R ): Flow<R>
  • 22. Custom
 Operator fun <T : Number> Flow<T>.sqrts(): Flow<Double> { return flow { // this: FlowCollector<Double> collect { number -> val value = sqrt(number.toDouble()) emit(value) } } }
  • 23. Custom
 Operator fun <T : Number> Flow<T>.sqrts(): Flow<Double> { return flow { // this: FlowCollector<Double> collect { number -> val value = sqrt(number.toDouble()) emit(value) } } } GlobalScope.launch { flowOf(1, 2, 3) .map { sqrt(it.toDouble()) } .sqrts() .collect() }
  • 24. Custom
 Operator fun <T : Number> Flow<T>.sqrts(): Flow<Double> { return flow { // this: FlowCollector<Double> collect { number -> val value = sqrt(number.toDouble()) emit(value) } } } GlobalScope.launch { flowOf(1, 2, 3) .map { sqrt(it.toDouble()) } .sqrts() .collect() }
  • 29. Concurrent Flow fun <T> Flow<T>.buffer( capacity: Int = Channel.UNLIMITED ): Flow<T> = flow { val channel = coroutineScope.produce(capacity) { collect { send(it) } } channel.consumeEach { emit(it) } }
  • 30. Concurrent Flow fun <T> Flow<T>.buffer(capacity: Int): Flow<T> fun <T> Flow<T>.produceIn( scope: CoroutineScope ): ReceiveChannel<T> fun <T> Flow<T>.broadcastIn( scope: CoroutineScope, start: CoroutineStart = CoroutineStart.LAZY ): BroadcastChannel<T> fun <T> channelFlow( block: suspend ProducerScope<T>.() -> Unit ): Flow<T>
  • 32. • Context preservation
 Flow encapsulates its own execution context and never propagates or leaks it downstream Flow Constraints
  • 34. Context Preservation flow { withContext(Dispatchers.Default) { emit(longComputation()) } } java.lang.IllegalStateException: Flow invariant is violated: flow was collected in [Context A info], but emission happened in [Context B info]. Please refer to 'flow' documentation or use 'flowOn' instead
  • 35. Context Preservation flow { emit(longComputation()) } .flowOn(Dispatchers.Default)
  • 36. Context Preservation flow { GlobalScope.launch(Dispatchers.IO) // is prohibited withContext(Dispatchers.Default) // is prohibited emit(1) // OK coroutineScope {
 emit(2) // OK -- still the same coroutine
 } }
  • 37. • Context preservation
 Flow encapsulates its own execution context and never propagates or leaks it downstream • Exception transparency
 Flow implementations never catch or handle exceptions that occur in downstream <ows Flow Constraints
  • 38. flow<Any> { try { emitValue() } catch (e: Exception) { println("Error handled $e") } } .map { process1() } .collect { process2() } Exception Transparency
  • 39. flow<Any> { emitValue() } .map { process1() } // catches exceptions in emitValue() and process1() .catch { e -> println("Error handled $e") } // throws exceptions from process2() .collect { process2() } Exception Transparency
  • 41. interface Stream<D> { fun subscribe(callback: Callback<D>) fun unsubscribe(callback: Callback<D>) } interface Callback<D> { fun onNext(item: D) fun onError(error: Throwable) fun onCompleted() } Old ways adapter
  • 42. val stream = Stream<Value>() callbackFlow<Value> { // this: ProducerScope<Value> // ProducerScope<Value> extends SendChannel<Value> val callback = object : Callback<Value> { override fun onNext(item: Value) { offer(item) } override fun onError(error: Throwable) { close(error) } override fun onCompleted() { close() } } stream.subscribe(callback) awaitClose { stream.unsubscribe(callback) } } Old ways adapter
  • 44. RxJava Operator fun <T> Observable<T>.filter( predicate: (T) -> Boolean ): Observable<T> = ObservableFilter(this, predicate)
  • 45. RxJava Operator class ObservableFilter<T>( private val source: ObservableSource<T>, private val predicate: (T) -> Boolean ) : Observable<T>(), HasUpstreamObservableSource<T> { override fun source(): ObservableSource<T> = source override fun subscribeActual(observer: Observer<in T>) { source.subscribe(FilterObserver(observer, predicate)) } internal class FilterObserver<T>( actual: Observer<in T>, private val filter: (T) -> Boolean ) : BasicFuseableObserver<T, T>(actual) { override fun onNext(t: T) { if (sourceMode == QueueFuseable.NONE) { try { if (filter(t)) downstream.onNext(t) } catch (e: Throwable) { fail(e) } } else { downstream.onNext(null) } } override fun requestFusion(mode: Int) = transitiveBoundaryFusion(mode) override fun poll(): T? { while (true) { val v = qd.poll() if (v == null || filter(v)) return v } } } } fun <T> Observable<T>.filter( predicate: (T) -> Boolean ): Observable<T> = ObservableFilter(this, predicate)
  • 46. Flow Operator fun <T> Flow<T>.filter( predicate: suspend (T) -> Boolean ): Flow<T> { return flow { collect { if (predicate(it)) emit(it) } } }
  • 47. Migration from RxJava RxJava 2 Coroutine Single<T> Deferred<T> !❄ Maybe<T> Deferred<T?> !❄ Completable Job !❄ Observable<T> Channel<T> ! Flow<T> ❄ Flowable<T>
  • 48. fun <T> Observable<T>.toFlow(): Flow<T> fun <T> Single<T>.toFlow(): Flow<T> fun <T> Maybe<T>.toFlow(): Flow<T> fun <T> Flowable<T>.toFlow(): Flow<T> RxJava2 to Flow Adapters
  • 49. fun <T> Observable<T>.toFlow(): Flow<T> fun <T> Single<T>.toFlow(): Flow<T> fun <T> Maybe<T>.toFlow(): Flow<T> fun <T> Flowable<T>.toFlow(): Flow<T> NO FROM THE BOX :) WRITE YOU OWNRxJava2 to Flow Adapters
  • 51. @Dao interface SampleDao { } // Request data and observe changes with RxJava @Query("SELECT * FROM ENTITIES") fun queryEntities(): Observable<List<Entity>>Room // Blocking request data @Query("SELECT * FROM ENTITIES") fun queryEntities(): List<Entity>
  • 52. @Dao interface SampleDao { } // Request data and observe changes with RxJava @Query("SELECT * FROM ENTITIES") fun queryEntities(): Observable<List<Entity>>Room // Blocking request data @Query("SELECT * FROM ENTITIES") fun queryEntities(): List<Entity> // Request data using Coroutines @Query("SELECT * FROM ENTITIES") suspend fun queryEntities(): List<Entity>
  • 53. @Dao interface SampleDao { } // Request data and observe changes with RxJava @Query("SELECT * FROM ENTITIES") fun queryEntities(): Observable<List<Entity>>Room // Blocking request data @Query("SELECT * FROM ENTITIES") fun queryEntities(): List<Entity> // Request data using Coroutines @Query("SELECT * FROM ENTITIES") suspend fun queryEntities(): List<Entity> // Request data and observe changes using Coroutines @Query("SELECT * FROM ENTITIES") fun queryEntities(): Flow<List<Entity>>
  • 54. val database = getSampleDatabase() GlobalScope.launch { database.sampleDao.queryEntities().collect { // Handle updates of entities } } Room
  • 55. interface GitHubService { } RetroZt @GET("users/{user}/repos") fun listRepos( @Path("user") user: String ): Call<List<Repo>>
  • 56. interface GitHubService { } RetroZt @GET("users/{user}/repos") suspend fun listRepos( @Path("user") user: String ): List<Repo> @GET("users/{user}/repos") fun listRepos( @Path("user") user: String ): Call<List<Repo>>
  • 57. interface GitHubService { } RetroZt @GET("users/{user}/repos") suspend fun listRepos( @Path("user") user: String ): List<Repo> @GET("users/{user}/repos") fun listRepos( @Path("user") user: String ): Flow<List<Repo>> @GET("users/{user}/repos") fun listRepos( @Path("user") user: String ): Call<List<Repo>>
  • 58. fun <T> Call<T>.asFlow(): Flow<T> = callbackFlow { enqueue(object : Callback<T> { override fun onFailure(call: Call<T>, error: Throwable) { close(error) } override fun onResponse(call: Call<T>, response: Response<T>) { if (response.isSuccessful) { offer(response.body()!!) close() } else { close(RetrofitError(response.errorBody())) } } }) awaitClose { if (!isCanceled) { cancel() } } } class RetrofitError(val errorBody: ResponseBody?) : Throwable() RetroZt
  • 59. val service = getGitHubService() GlobalScope.launch { service.listRepos("user-id") .asFlow() .collect { // handle response } } RetroZt
  • 60. • Flow will be primary way to handle async stream of data • Channels will be used: • for hot streams • “under-the-hood” in some Flow operators • as synchronization primitive between Coroutines What will be the next?