- Flow will return a continuous stream of data rather than returning the value at the end.
- Flow will not block the main thread and runs Asynchronous.
- Return values continuosly vs return at once:
Kotlin Coroutines
├── Flows
│ ├── StateFlow
│ └── SharedFlow
└── Channels
// Factorial of a number: 5
// at once :
25ms : 1
25ms : 2
25ms : 6
25ms : 24
25ms : 120
// Factorial of a number:
// continuos :
51ms : 1
63ms : 2
75ms : 6
88ms : 24
99ms : 120
- Flow vs Suspend:
- Cold vs Hot Flows
Flow Builders:
- flow(): Creates a flow from a suspend function that can emit multiple values.
- Here flow{} creates a coroutine scope so that you could use any suspend functions
fun main() = runBlocking {
val flow = flow {
for (i in 1..3) {
delay(100) // Simulate some work
emit(i) // Emit each value after a delay of 100ms
emitAll(secondFlow) // emitAll is used to emit the values from another flowff
}
}
flow.collect { println(it) } // Collect and print each value emitted by the flow and by the second flow
}
- flowOf(): Creates a flow that emits a fixed set of values.
fun main() = runBlocking {
val flow = flowOf(1, 2, 3) // Create a flow that emits the values 1, 2, and 3
flow.collect { println(it) } // Collect and print each value emitted by the flow
}
- asFlow(): Converts any iterable, suspend function, or callback-based API into a flow.
fun main() = runBlocking {
val list = listOf(1, 2, 3) // Create a list of values
val flow = list.asFlow() // Convert the list into a flow
flow.collect { println(it) } // Collect and print each value emitted by the flow
}
Terminal flow operators
- Terminal operators on flows are suspending functions that start a collection of the flow. The collect operator is the most basic one.
first() and last(): Returns the first or last emitted value, or throws an exception if the flow completes without emitting any values.
val numbers = flowOf(1, 2, 3)
lifecycleScope.launch {
val value = numbers.first()
val value = numbers.firstOrNull() // you can use to return null if empty
// value is 1
}
// Also
lifecycleScope.launch {
val value = numbers.first{it>2}
// value is 2,3
single(): Returns a single emitted value, throws an exception if the flow emits more than one value, or completes without emitting any values.
val numbers = flowOf(1) // should be only one value to use single
lifecycleScope.launch {
val value = numbers.single()
// value is 1
}