0
0
KotlinHow-ToBeginner · 3 min read

How to Use SharedFlow in Kotlin: Simple Guide and Example

In Kotlin, SharedFlow is a hot flow that lets multiple collectors receive the same emitted values. You create a MutableSharedFlow to emit values and collect them using collect in coroutines. It is useful for broadcasting events to many listeners.
📐

Syntax

SharedFlow is created using MutableSharedFlow which allows emitting values. You collect values from it using collect inside a coroutine.

  • MutableSharedFlow<T>(): Creates a shared flow of type T.
  • emit(value): Sends a value to all collectors.
  • collect { value -> }: Receives values from the flow.
kotlin
val sharedFlow = MutableSharedFlow<Int>()

// Emitting values
suspend fun emitValue(value: Int) {
    sharedFlow.emit(value)
}

// Collecting values
suspend fun collectValues() {
    sharedFlow.collect { value ->
        println("Received: $value")
    }
}
💻

Example

This example shows how to create a MutableSharedFlow, emit values from one coroutine, and collect them from another coroutine.

kotlin
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*

fun main() = runBlocking {
    val sharedFlow = MutableSharedFlow<String>()

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

    // Collector 2
    launch {
        sharedFlow.collect { value ->
            println("Collector 2 received: $value")
        }
    }

    // Emit values
    launch {
        val messages = listOf("Hello", "Kotlin", "SharedFlow")
        for (msg in messages) {
            sharedFlow.emit(msg)
            delay(100) // simulate work
        }
    }

    delay(500) // wait for all emissions
}
Output
Collector 1 received: Hello Collector 2 received: Hello Collector 1 received: Kotlin Collector 2 received: Kotlin Collector 1 received: SharedFlow Collector 2 received: SharedFlow
⚠️

Common Pitfalls

One common mistake is expecting SharedFlow to replay past values by default. By default, it does not replay any value unless configured with replay. Also, emit is a suspend function and must be called from a coroutine.

Another pitfall is not launching collectors before emitting values, which causes collectors to miss emissions.

kotlin
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*

fun main() = runBlocking {
    val sharedFlow = MutableSharedFlow<Int>()

    // Emitting before collecting - collectors will miss these
    launch {
        sharedFlow.emit(1)
        sharedFlow.emit(2)
    }

    delay(100) // delay before collector starts

    // Collector starts late
    launch {
        sharedFlow.collect { value ->
            println("Received: $value")
        }
    }

    delay(200)
}

// Correct way: start collectors before emitting
fun correctUsage() = runBlocking {
    val sharedFlow = MutableSharedFlow<Int>()

    launch {
        sharedFlow.collect { value ->
            println("Received: $value")
        }
    }

    launch {
        sharedFlow.emit(1)
        sharedFlow.emit(2)
    }

    delay(200)
}
Output
Received: 1 Received: 2
📊

Quick Reference

  • MutableSharedFlow<T>(): Create a shared flow.
  • emit(value): Send value to all collectors.
  • collect { }: Receive values.
  • replay: Number of past values to replay to new collectors.
  • extraBufferCapacity: Buffer size for emissions without suspending.

Key Takeaways

SharedFlow lets multiple coroutines receive the same emitted values simultaneously.
Always start collectors before emitting to avoid missing values.
Use MutableSharedFlow to emit values and collect to receive them.
Configure replay to send past values to new collectors if needed.
Emit is a suspend function and must be called from a coroutine.