Hot Flow vs Cold Flow in Kotlin Coroutines

In Kotlin Coroutines, Flow can be categorized into Cold Flows and Hot Flows based on how they emit values and manage their state.


Cold Flow

  • Definition: A Cold Flow is lazy and starts emitting values only when an active collector exists.
  • Behavior: Every time a new collector subscribes, the flow restarts and produces fresh data.
  • Examples: flow {}, flowOf(), asFlow(), channelFlow {}.

Example of Cold Flow in Jetpack Compose

@Composable
fun ColdFlowExample() {
    val flow = flow {
        for (i in 1..5) {
            delay(1000)
            emit(i)
        }
    }

    val scope = rememberCoroutineScope()
    var text by remember { mutableStateOf("Waiting...") }

    LaunchedEffect(Unit) {
        flow.collect { value ->
            text = "Cold Flow Emitted: $value"
        }
    }

    Text(text = text, fontSize = 20.sp, modifier = Modifier.padding(16.dp))
}

Explanation

  • The flow emits values every second.
  • When LaunchedEffect starts, the collector receives values.
  • Each new collector gets fresh emissions from the beginning.

Hot Flow

  • Definition: A Hot Flow emits values continuously, even without collectors.
  • Behavior: The emission does not restart for every collector.
  • Examples: StateFlow, SharedFlow, MutableStateFlow, MutableSharedFlow.

Example of Hot Flow using StateFlow in Jetpack Compose

class HotFlowViewModel : ViewModel() {
    private val _stateFlow = MutableStateFlow(0) // Initial state
    val stateFlow: StateFlow<Int> = _stateFlow.asStateFlow()

    init {
        viewModelScope.launch {
            while (true) {
                delay(1000)
                _stateFlow.value += 1
            }
        }
    }
}

@Composable
fun HotFlowExample(viewModel: HotFlowViewModel = viewModel()) {
    val count by viewModel.stateFlow.collectAsState()

    Text(text = "Hot Flow Counter: $count", fontSize = 20.sp, modifier = Modifier.padding(16.dp))
}

Explanation

  • MutableStateFlow holds a state that is updated every second.
  • Even if no collectors exist, stateFlow keeps its last emitted value.
  • When collectAsState() is called, it emits the latest value instead of restarting.

Key Differences

Feature Cold Flow Hot Flow
Starts Emitting When collected Immediately (even without collectors)
Replays Values No (new collector starts fresh) Yes (new collector gets the latest value)
Examples flow {}, flowOf(), asFlow() StateFlow, SharedFlow
Use Case Fetching fresh data from API UI State management

Cold vs Hot Flow with SharedFlow

If you want hot flow behavior but also want to replay some past emissions, use SharedFlow.

Example using SharedFlow

class SharedFlowViewModel : ViewModel() {
    private val _sharedFlow = MutableSharedFlow<Int>(replay = 2) // Replays last 2 values
    val sharedFlow: SharedFlow<Int> = _sharedFlow.asSharedFlow()

    init {
        viewModelScope.launch {
            var count = 0
            while (true) {
                delay(1000)
                _sharedFlow.emit(count++)
            }
        }
    }
}

@Composable
fun SharedFlowExample(viewModel: SharedFlowViewModel = viewModel()) {
    val scope = rememberCoroutineScope()
    var text by remember { mutableStateOf("Waiting...") }

    LaunchedEffect(Unit) {
        scope.launch {
            viewModel.sharedFlow.collect { value ->
                text = "Shared Flow Emitted: $value"
            }
        }
    }

    Text(text = text, fontSize = 20.sp, modifier = Modifier.padding(16.dp))
}

Explanation

  • MutableSharedFlow is a hot flow that emits values every second.
  • It replays the last 2 values for new collectors.
  • Unlike StateFlow, it does not hold a default value.

When to Use What?

Use Case Recommended Flow
Fetching fresh API data Cold Flow
UI state that persists across collectors StateFlow
Broadcasting events to multiple collectors SharedFlow

Conclusion

  • Cold Flow is useful when you need fresh emissions per collection (like API calls).
  • Hot Flow (StateFlow, SharedFlow) is useful for UI state management and broadcasting updates.
  • Use StateFlow for single state holder and SharedFlow for event-based broadcasting.

0 comments:

Post a Comment