skip to content

flowOf / asFlow Builders

flowOf wraps fixed values and asFlow converts an Iterable, Sequence, or range into a Flow. They are the quick on-ramps, and they carry the same cold semantics as the flow builder.

part ofKotlinoverview, primer and where to startread it →
on this pageshow

questions

5

What does flowOf(...) do, and how does it differ from a list of values?

level: juniorimportance: must knowfreq 60%

answer

  1. flowOf = shorthand for flow { emit(...) }
  2. Cold: re-emits on every collect
  3. flowOf() with no args = emptyFlow()
  4. List = eager memory; Flow = lazy stream
  5. collect is suspend

basics

~10 s

flowOf takes a fixed set of values and wraps them in a Flow, emitting each one in order when you collect it. A list just holds values; a Flow streams them on demand.

solid answer

~30 s

flowOf(a, b, c) is a convenience cold-flow builder that emits the given fixed values in order, then completes. It is essentially shorthand for flow { emit(a); emit(b); emit(c) }. Being cold, nothing runs until a terminal operator like collect() is called, and the values are re-emitted on every collection. Unlike a List (an in-memory eager collection), a Flow is a lazy stream you observe with suspending collectors, so it composes with operators (map, filter), runs inside a coroutine, and supports backpressure via suspension. There is also a zero-arg flowOf() that produces an empty flow, equivalent to emptyFlow().

code

kotlin · 7 lines
kotlin
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.runBlocking

fun main() = runBlocking {
    val nums = flowOf(10, 20, 30)
    nums.collect { println(it) } // 10 20 30
}

go deeper

for a junior

Knows flowOf emits fixed values when collected and that a flow is lazy, unlike a list.

for a middle

Explains cold semantics, equivalence to flow { emit }, and the empty/single-arg variants.

for a senior

Discusses where flowOf fits in a pipeline, backpressure via suspension, and when asFlow is preferable.

for a principal

Frames cold builders within the broader reactive/coldness model and trade-offs vs hot SharedFlow seeds.

## What flowOf is `flowOf` is one of Kotlin's **convenience cold-flow builders** in `kotlinx.coroutines.flow`. It takes a fixed, known set of values and returns a `Flow<T>` that emits them in order. ```kotlin val flow: Flow<Int> = flowOf(1, 2, 3) ``` This is equivalent to writing the more verbose `flow { }` builder: ```kotlin val flow = flow { emit(1) emit(2) emit(3) } ``` ## Cold means lazy **Cold** means the builder does nothing until a **terminal operator** (such as `collect`) runs. Each collection re-executes the emission from scratch: ```kotlin val f = flowOf(1, 2, 3) f.collect { print(it) } // prints 123 f.collect { print(it) } // prints 123 again ``` ## Flow vs List - A `List<Int>` is an **eager, in-memory collection** — all elements exist at once. - A `Flow<Int>` is a **lazy asynchronous stream** — values are produced one at a time when collected. - Collecting a flow happens inside a **coroutine**; `collect` is a `suspend` function. - Flows compose with operators like `map`, `filter`, `onEach`; suspension provides natural **backpressure**. ## Empty and single variants - `flowOf()` (no args) returns an empty flow — same as `emptyFlow<T>()`. - `flowOf(x)` (one arg) is a single-value flow. ## When to use it Use `flowOf` for **fixed, literal values** you want to feed into a flow pipeline — for tests, defaults, or seeding a chain of operators. For values you already hold in a collection, prefer `asFlow()` instead.

  • What does flowOf() with no arguments produce?
    An empty flow that completes immediately without emitting anything, equivalent to emptyFlow().
  • If you collect the same flowOf twice, what happens?
    It re-emits all values both times, because flows are cold and each collection restarts the emission.

flowOf is like a player piano roll: the notes are fixed, but they only play when someone presses start.

saying these in an interview costs you the question

  • Calling a Flow 'just a list with extra steps'
  • Thinking flowOf runs immediately when constructed
  • Believing the values are emitted only once across multiple collectors
  • Confusing flowOf with a hot stream like StateFlow

context

open as a page

How does asFlow() work for Iterable and Sequence, and when would you use it over flowOf?

level: middleimportance: must knowfreq 50%

basics

~20 s

asFlow() is an extension that turns something you already have — a list, sequence, or range — into a Flow that emits each element. Use it when the values live in a collection; use flowOf for literal values you type out.

open as a page

How do you build a flow from a numeric range or an array, and what are the gotchas with large ranges?

level: middleimportance: should knowfreq 35%

basics

~10 s

Use (1..n).asFlow() for a range or myArray.asFlow() for an array. Each number or element is emitted in order. With huge ranges, prefer asFlow over flowOf so you don't pass thousands of varargs.

open as a page

Explain the (() -> T).asFlow() and (suspend () -> T).asFlow() overloads. How do they differ from flow { emit(...) } and from flowOf(producer())?

level: seniorimportance: should knowfreq 25%

basics

~20 s

These overloads take a function (optionally suspending) and make a flow that calls it once per collection, emitting its single return value. flowOf(producer()) instead calls producer eagerly once, before collection, and reuses that fixed result.

open as a page

You wrap a side-effecting iterator-backed source with asFlow() and collect it twice — what happens, and how do these convenience builders preserve cold semantics?

level: seniorimportance: nice to knowfreq 18%

basics

~10 s

Because the flow is cold, collecting twice re-runs the source twice. If the source is a one-shot iterator already consumed, the second collect emits nothing. flowOf and asFlow keep this lazy, replay-per-collect behavior.

open as a page