Hot vs cold flows — Kotlin Coroutines

Hot vs cold flows — Kotlin Coroutines

In Kotlin, a hot flow is a type of flow that continuously emits values, even when there are no active collectors, such as with a SharedFlow or StateFlow.

On the other hand, a cold flow only starts producing and emitting values when at least one collector is actively collecting, as seen with a regular Flow.

But what does that actually mean?

Let’s dive into an example comparing a cold Flow with a hot SharedFlow to better understand the distinction.

Cold Flow Example

A cold flow only emits values when a collector is actively collecting. Each collector triggers a fresh emission sequence.

val coldFlow = flow {
    println("Emitting values...")
    emit(0) 
    emit(1)
}

launch {
    println("Starting cold flow collection...")
    coldFlow.collect { value ->
        println("Cold flow collector received: $value")
    }
}

// Result
Emitting values...
Starting cold flow collection...
Cold flow collector received: 0
Cold flow collector received: 1        

At the start, no emissions occur because there are no active collectors. Only when a collector subscribes does the flow start emitting values, triggering emit(0) and emit(1). This behavior is why it's said that cold flows "emit values only when there is an active collector."

Each new collector will restart the flow, receiving the same sequence of values [0, 1], as the emissions are re-triggered for every subscriber.

SharedFlow Example

A hot flow like SharedFlow emits values immediately, even if no collector is actively collecting at the time. Collectors receive values emitted after they start collecting.

val sharedFlow = MutableSharedFlow<Int>()

// Emitting a value before any collector starts
sharedFlow.emit(0)

launch {
    println("Starting SharedFlow collection...")
    sharedFlow.collect { value ->
        println("SharedFlow collector received: $value")
    }
}

// Emitting values after the collector starts
sharedFlow.emit(1)
sharedFlow.emit(2)

// Result 
Starting SharedFlow collection...
SharedFlow collector received: 1
SharedFlow collector received: 2        

Initially, it emits 0 immediately, but without any collectors, this value is essentially "missed." When a collector subscribes, it does not receive the earlier emissions because it was registered after the emission of 0.

Instead, the collector will pick up any subsequent emissions, such as [1, 2], resulting in those values being received.

StateFlow Example (Hot Flow with a Current State)

val stateFlow = MutableStateFlow(0) // Holds a default initial value

// Collector 1
launch {
    stateFlow.collect { value ->
        println("StateFlow Collector 1 received: $value")
    }
}

// Update stateFlow's value
stateFlow.value = 1
stateFlow.value = 2

// Collector 2 (starts collecting from the latest value)
launch {
    stateFlow.collect { value ->
        println("StateFlow Collector 2 received: $value")
    }
}

// Result 
StateFlow Collector 1 received: 0
StateFlow Collector 1 received: 1
StateFlow Collector 1 received: 2
StateFlow Collector 2 received: 2        

StateFlow always holds a current value and emits it immediately to any new collectors. In this example, Collector 2 receives the latest value (2) when it starts collecting, while Collector 1 gets all updates starting from the initial value.

To help you remember the difference:

Regular Flow

  • At the beginning, no values are emitted because there is no active collector.
  • When a collector subscribes, it triggers the flow’s emissions, starting with emit(0) and then emit(1). This behavior exemplifies the phrase: “only emits values when there is an active collector.”
  • If additional collectors subscribe in the future, the flow will re-trigger emissions for each new collector, and they will again receive [0, 1] as fresh emissions.


SharedFlow

  • Initially, SharedFlow emits 0, but since there are no active collectors at that time, the value is lost.
  • When a new collector subscribes, it does not receive past emissions that occurred before it subscribed (in this case, 0).
  • The collector will only receive future emissions, so the result is [1, 2].


StateFlow

  • Unlike SharedFlow, StateFlow retains the latest emitted value.
  • When a new collector subscribes, it immediately receives the most recent value, even if the emission occurred before the collector subscribed.
  • For example, if the most recent value emitted was 2, a new collector will instantly receive 2 upon subscription.


SOURAV JAISWAL

Proficient in C++ and Kotlin | Android Developer Specializing in Creating High-Performance, User-Centric Applications | Kotlin | MVVM | Retrofit | DaggerHilt

3 个月

Very informative

要查看或添加评论,请登录

Shubham Sharma的更多文章

  • Jetpack compose interview Q&A part 1

    Jetpack compose interview Q&A part 1

    1. Jetpack Compose vs.

  • Mastering LiveData and Flows in Android: An In-Depth Guide

    Mastering LiveData and Flows in Android: An In-Depth Guide

    In Android development, ensuring responsiveness and efficiency is key to building high-quality apps. LiveData and…

  • Top 10 Git Interview Questions

    Top 10 Git Interview Questions

    What’s the difference between Git and GitHub? Git and GitHub are related but serve different purposes in the context of…

    1 条评论
  • Jetpack Compose

    Jetpack Compose

    Jetpack Compose is a modern UI toolkit that is designed to simplify UI development in Android. It consists of a…

    2 条评论

社区洞察

其他会员也浏览了