As a part of kotlinx.coroutines 1.2 Flow was introduced as a cold asynchronous data stream. How does it work? What we can do with it? Is it that we waiting so long for replacing Rx? The talk has answers to them.
while (hasMore) send(nextValue) } } val values: ReceiveChannel<Value> = fooProducer(p) if (someCondition) { return anotherResult // Oops! Leaked channel } // ... do further work with values ...
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
(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/
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) }
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
/ 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/
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
never propagates or leaks it downstream • Exception transparency Flow implementations never catch or handle exceptions that occur in downstream <ows Flow Constraints
changes with RxJava @Query("SELECT * FROM ENTITIES") fun queryEntities(): Observable<List<Entity>> Room // Blocking request data @Query("SELECT * FROM ENTITIES") fun queryEntities(): List<Entity>
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>
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>>
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?