Skip to content

Commit d3627f7

Browse files
Add flow playground files
1 parent fd93948 commit d3627f7

36 files changed

+759
-0
lines changed

.idea/compiler.xml

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package com.lukaslechner.coroutineusecasesonandroid.playground.flow
2+
3+
import kotlinx.coroutines.delay
4+
import kotlinx.coroutines.flow.Flow
5+
import kotlinx.coroutines.flow.collect
6+
import kotlinx.coroutines.flow.flow
7+
import kotlinx.coroutines.launch
8+
import kotlinx.coroutines.runBlocking
9+
10+
// Sequence for synchronously computed values
11+
// Flow for asynchronously computed values
12+
13+
private fun simple(): Flow<Int> = flow { // flow builder
14+
for (i in 1..3) {
15+
delay(100) // pretend we are doing something useful here
16+
emit(i) // emit next value
17+
}
18+
}
19+
20+
fun main() = runBlocking<Unit> {
21+
// Launch a concurrent coroutine to check if the main thread is blocked
22+
launch {
23+
for (k in 1..3) {
24+
println("I'm not blocked $k")
25+
delay(100)
26+
}
27+
}
28+
// Collect the flow
29+
simple().collect { value -> println(value) }
30+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package com.lukaslechner.coroutineusecasesonandroid.playground.flow
2+
3+
import kotlinx.coroutines.flow.Flow
4+
import kotlinx.coroutines.flow.collect
5+
import kotlinx.coroutines.flow.flow
6+
import kotlinx.coroutines.runBlocking
7+
8+
private fun log(msg: String) = println("[${Thread.currentThread().name}] $msg")
9+
10+
// Context preservation
11+
// Collection of a flow always happens in the context of the calling coroutine.
12+
13+
private fun simple(): Flow<Int> = flow {
14+
log("Started simple flow")
15+
for (i in 1..3) {
16+
emit(i)
17+
}
18+
}
19+
20+
fun main() = runBlocking<Unit> {
21+
simple().collect { value -> log("Collected $value") }
22+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package com.lukaslechner.coroutineusecasesonandroid.playground.flow
2+
3+
import kotlinx.coroutines.Dispatchers
4+
import kotlinx.coroutines.flow.Flow
5+
import kotlinx.coroutines.flow.collect
6+
import kotlinx.coroutines.flow.flow
7+
import kotlinx.coroutines.runBlocking
8+
9+
// Flow always has to emit in the context in which it was collected
10+
11+
private fun simple(): Flow<Int> = flow {
12+
// The WRONG way to change context for CPU-consuming code in flow builder
13+
kotlinx.coroutines.withContext(Dispatchers.Default) {
14+
for (i in 1..3) {
15+
Thread.sleep(100) // pretend we are computing it in CPU-consuming way
16+
emit(i) // emit next value
17+
}
18+
}
19+
}
20+
21+
fun main() = runBlocking<Unit> {
22+
simple().collect { value -> println(value) }
23+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package com.lukaslechner.coroutineusecasesonandroid.playground.flow
2+
3+
import kotlinx.coroutines.Dispatchers
4+
import kotlinx.coroutines.flow.Flow
5+
import kotlinx.coroutines.flow.collect
6+
import kotlinx.coroutines.flow.flow
7+
import kotlinx.coroutines.flow.flowOn
8+
import kotlinx.coroutines.runBlocking
9+
10+
private fun log(msg: String) = println("[${Thread.currentThread().name}] $msg")
11+
12+
private fun simple(): Flow<Int> = flow {
13+
for (i in 1..3) {
14+
Thread.sleep(100) // pretend we are computing it in CPU-consuming way
15+
log("Emitting $i")
16+
emit(i) // emit next value
17+
}
18+
}.flowOn(Dispatchers.Default) // RIGHT way to change context for CPU-consuming code in flow builder
19+
20+
// flowOn creates another coroutine for an upstream flow when it has to change the CoroutineDispatcher in its context
21+
22+
fun main() = runBlocking<Unit> {
23+
simple().collect { value ->
24+
log("Collected $value")
25+
}
26+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package com.lukaslechner.coroutineusecasesonandroid.playground.flow
2+
3+
import kotlinx.coroutines.delay
4+
import kotlinx.coroutines.flow.Flow
5+
import kotlinx.coroutines.flow.buffer
6+
import kotlinx.coroutines.flow.collect
7+
import kotlinx.coroutines.flow.flow
8+
import kotlinx.coroutines.runBlocking
9+
import kotlin.system.measureTimeMillis
10+
11+
private fun simple(): Flow<Int> = flow {
12+
for (i in 1..3) {
13+
delay(100) // pretend we are asynchronously waiting 100 ms
14+
emit(i) // emit next value
15+
}
16+
}
17+
18+
fun main() = runBlocking<Unit> {
19+
val time = measureTimeMillis {
20+
simple()
21+
.buffer() // without buffer, code takes 1235ms to complete, otherwise 100
22+
.collect { value ->
23+
delay(300) // pretend we are processing it for 300 ms
24+
println(value)
25+
}
26+
}
27+
println("Collected in $time ms")
28+
}
29+
30+
// we have effectively created a processing pipeline
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package com.lukaslechner.coroutineusecasesonandroid.playground.flow
2+
3+
import kotlinx.coroutines.delay
4+
import kotlinx.coroutines.flow.Flow
5+
import kotlinx.coroutines.flow.collect
6+
import kotlinx.coroutines.flow.conflate
7+
import kotlinx.coroutines.flow.flow
8+
import kotlinx.coroutines.runBlocking
9+
import kotlin.system.measureTimeMillis
10+
11+
// Speed up processing when both the emitter and collector are slow
12+
// it drops emitted values
13+
14+
private fun simple(): Flow<Int> = flow {
15+
for (i in 1..3) {
16+
delay(100) // pretend we are asynchronously waiting 100 ms
17+
emit(i) // emit next value
18+
}
19+
}
20+
21+
fun main() = runBlocking<Unit> {
22+
val time = measureTimeMillis {
23+
simple()
24+
.conflate() // conflate emissions, don't process each one
25+
.collect { value ->
26+
delay(300) // pretend we are processing it for 300 ms
27+
println(value)
28+
}
29+
}
30+
println("Collected in $time ms")
31+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package com.lukaslechner.coroutineusecasesonandroid.playground.flow
2+
3+
import kotlinx.coroutines.delay
4+
import kotlinx.coroutines.flow.Flow
5+
import kotlinx.coroutines.flow.collectLatest
6+
import kotlinx.coroutines.flow.flow
7+
import kotlinx.coroutines.runBlocking
8+
import kotlin.system.measureTimeMillis
9+
10+
private fun simple(): Flow<Int> = flow {
11+
for (i in 1..3) {
12+
delay(100) // pretend we are asynchronously waiting 100 ms
13+
emit(i) // emit next value
14+
}
15+
}
16+
17+
fun main() = runBlocking<Unit> {
18+
val time = measureTimeMillis {
19+
simple()
20+
.collectLatest { value -> // cancel & restart on the latest value
21+
println("Collecting $value")
22+
delay(300) // pretend we are processing it for 300 ms
23+
println("Done $value")
24+
}
25+
}
26+
println("Collected in $time ms")
27+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package com.lukaslechner.coroutineusecasesonandroid.playground.flow
2+
3+
import kotlinx.coroutines.flow.asFlow
4+
import kotlinx.coroutines.flow.collect
5+
import kotlinx.coroutines.flow.flowOf
6+
import kotlinx.coroutines.flow.zip
7+
import kotlinx.coroutines.runBlocking
8+
9+
fun main() = runBlocking<Unit> {
10+
11+
val numbers = (1..3).asFlow()
12+
val strings = flowOf("one", "two", "three")
13+
numbers.zip(strings) { a, b -> "$a -> $b" } // compose a single string
14+
.collect { println(it) } // collect and print
15+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package com.lukaslechner.coroutineusecasesonandroid.playground.flow
2+
3+
import kotlinx.coroutines.delay
4+
import kotlinx.coroutines.flow.*
5+
import kotlinx.coroutines.runBlocking
6+
7+
fun main() = runBlocking<Unit> {
8+
9+
val numbers = (1..3).asFlow()
10+
.onEach { delay(300) }
11+
12+
val strings = flowOf("one", "two", "three")
13+
.onEach { delay(400) }
14+
15+
val startTime = System.currentTimeMillis() // remember the start time
16+
numbers.combine(strings) { a, b -> "$a -> $b" } // compose a single string with "zip"
17+
.collect { value -> // collect and print
18+
println("$value at ${System.currentTimeMillis() - startTime} ms from start")
19+
}
20+
}

0 commit comments

Comments
 (0)