Kotlin Flow Builders

In this lesson, you’ll continue your exploration of Kotlin Flow by focusing on four key flow builders: flow, asFlow, flowOf, and callbackFlow. These builders are the backbone of creating reactive streams in Kotlin.

Flow builders in Kotlin are functions that help you create instances of a flow — a type of cold stream that doesn’t start emitting items until a consumer starts collecting. You’ll learn more about cold and hot streams in later lessons.

Each builder has its specific use case:

  • flow is the most generic builder, perfect for executing arbitrary code that emits items over time.
  • asFlow turns various data types into a flow.
  • flowOf creates a flow from a fixed set of values.
  • callbackFlow integrates callback-based APIs.

The flow Builder

In your carrot factory theme, suppose you want to fetch a fresh batch of carrots from the field asynchronously and emit the batch for further processing:

fun fetchCarrotBatch(): Flow<List<Carrot>> = flow {
  val freshBatch = api.fetchNewCarrots()
  emit(freshBatch)
}

You use the flow builder when you want to emit a series of values sequentially. It’s useful when these values are generated asynchronously.

The asFlow Builder

Imagine you have a couple of carrots already picked and ready for processing. If you wanted to include them in the processing line, you could turn them into a flow like this:

fun List<Carrot>.toFlow(): Flow<Carrot> = asFlow()

val carrotList = listOf(Carrot(), Carrot(), Carrot())
carrotList.toFlow()
  .collect { carrot -> process(carrot) }

The asFlow builder converts existing collections or sequences into a flow. It’s a simple way to turn data you already have into a reactive stream.

The flowOf Builder

If you have preferred types of carrot you need to prepare for a special order, you could include those types in the production line like this:

val favoriteCarrotTypes = flowOf("Nantes", "Imperator", "Chantenay")
favoriteCarrotTypes
  .collect { type -> println(type) }

The flowOf builder is similar to asFlow, but it’s typically used when you have a known set of items to emit as a flow. It’s often used for emitting a small number of values.

The callbackFlow Builder

In your carrot factory, you have a sorting machine that calls you back — pun intended — when it sorts some carrots. If you wanted to include those carrots in the production line, you could do something like this:

fun watchCarrotSortingProcess(): Flow<CarrotEvent> = callbackFlow {
  val callback = object : CarrotSortingCallback {
    override fun onSorted(event: CarrotEvent) {
      trySend(event).isSuccess
    }
  }
  sortingMachine.registerCallback(callback)
  awaitClose { sortingMachine.unregisterCallback(callback) }
}

watchCarrotSortingProcess()
  .collect { event -> handleSortingEvent(event) }

The callbackFlow builder is particularly powerful when dealing with callback-based APIs or events. It lets you convert these into a flow, which can be managed within the reactive streams paradigm.

Collecting the Flow

You’ve probably noticed the collect function popping up in most of the examples. collect is essential in Kotlin Flow. It’s where the stream of data gets consumed. This function is called on a flow to handle each item it emits, performing actions like updating a UI, processing data, or storing results. It’s the active endpoint that triggers the execution of the flow, making it a vital component in realizing the practical app of your data streams. Keep this in mind as you proceed, as collect is what brings your data flows to life in real-world apps.

Wrap-Up

In this lesson, you’ve covered the foundational flow builders in Kotlin and seen how they can be applied in the context of a carrot factory. Understanding these builders allows you to manage asynchronous data streams effectively, making your apps more responsive and efficient. You’ve also learned how to collect the data streams created with Kotlin Flow.

In the next lesson, you’ll go through a short demo where you’ll get a chance to use each of these builders. Stay tuned!

See forum comments
Download course materials from Github
Previous: Core Concepts Next: Flow Builder Demo