Kotlin Flow vs StateFlow vs SharedFlow: Android-interviewvragen in 2026
De Kotlin Flow vs StateFlow vs SharedFlow-vragen die Android-interviewers in 2026 stellen, met heldere antwoorden, een vergelijkingstabel en productieklare code.

Kotlin Flow vs StateFlow vs SharedFlow is een van de vaakst voorkomende onderwerpen tijdens Android-sollicitatiegesprekken in 2026, en de drie door elkaar halen kost al snel een coroutines-ronde. StateFlow en SharedFlow zijn allebei hot streams die op Flow zijn gebouwd, maar ze bestaan om verschillende problemen op te lossen: state vasthouden versus events uitzenden. De onderstaande vragen zijn de vragen die Android-interviewers daadwerkelijk stellen, met precieze antwoorden en productieklare code.
Een Flow is cold en draait de producer één keer per collector. StateFlow is een hot, geconflateerde stream die altijd één huidige waarde vasthoudt, ideaal voor UI-state. SharedFlow is een hot stream zonder verplichte beginwaarde, ideaal voor eenmalige events zoals navigatie of een snackbar.
Kotlin Flow vs StateFlow vs SharedFlow: de kernverschillen
StateFlow en SharedFlow zijn specialisaties van SharedFlow, dat zelf een hot Flow is. Waar interviewers naar peilen is cold versus hot, of er een huidige waarde bewaard blijft, en hoe elk type omgaat met dubbele emissies. Een beknopt mentaal model: Flow is een recept, StateFlow is één enkele mutable waarde en SharedFlow is een event bus.
| Eigenschap | Flow (cold) | StateFlow | SharedFlow |
|---|---|---|---|
| Temperatuur | Cold | Hot | Hot |
| Beginwaarde | Geen | Verplicht | Optioneel (via replay) |
| Houdt huidige waarde vast | Nee | Ja, via .value | Nee |
| Zendt duplicaten uit | Ja | Nee (geconflateerd + ontdubbeld) | Instelbaar |
| Extra collectors | Elke keer een nieuwe stream | Gedeeld | Gedeeld |
| Geschikt voor | Async datapijplijnen | UI-state | Eenmalige events |
De officiële Kotlin-coroutinesdocumentatie beschouwt dit cold-by-default-gedrag als de bepalende eigenschap van Flow, dus een sterk antwoord begint daar.
Waarom is een Kotlin Flow standaard cold?
Een cold flow doet niets totdat collect() wordt aangeroepen, en voert zijn producerblok opnieuw uit voor elke collector. Twee collectors op dezelfde cold flow veroorzaken twee onafhankelijke netwerkaanroepen. Dit is het meest geteste concept, dus een kort voorbeeld verankert het antwoord.
fun searchResults(query: String): Flow<List<Result>> = flow {
// This block runs fresh for every collector.
// Nothing executes until a collector calls collect().
val results = api.search(query) // suspending network call
emit(results) // pushed downstream to the collector
}Doordat de producer per collector opnieuw start, zijn cold flows de juiste standaard voor datapijplijnen die op aanvraag moeten draaien. Ze worden pas een probleem wanneer een waarde over een heel scherm gedeeld moet worden, en precies daar komen StateFlow en SharedFlow in beeld.
StateFlow-interviewvragen: state die altijd een waarde uitzendt
StateFlow is een hot flow die altijd een waarde heeft en die laatste waarde opnieuw afspeelt naar elke nieuwe collector. Het vereist een beginwaarde, stelt .value beschikbaar voor synchrone reads en conflateert emissies: snelle opeenvolgende updates kunnen tussenliggende waarden overslaan, en dezelfde waarde twee keer instellen zendt niets uit omdat er op basis van gelijkheid wordt ontdubbeld. Daarmee is het de moderne vervanger van LiveData in een ViewModel.
class SearchViewModel(private val repo: SearchRepository) : ViewModel() {
// MutableStateFlow demands an initial value, so the UI always has something to render.
private val _uiState = MutableStateFlow<SearchUiState>(SearchUiState.Idle)
val uiState: StateFlow<SearchUiState> = _uiState.asStateFlow()
fun onQueryChanged(query: String) {
_uiState.value = SearchUiState.Loading
viewModelScope.launch {
val results = repo.search(query)
// update {} applies the change atomically, safe under concurrent callers.
_uiState.update { SearchUiState.Success(results) }
}
}
}Een veelgestelde vervolgvraag: waarom asStateFlow() blootstellen in plaats van het mutable veld? Het geeft de UI een alleen-lezen weergave, zodat de state alleen via de ViewModel kan wijzigen, wat de unidirectionele data flow intact houdt. De eigen StateFlow- en SharedFlow-gids van Android beveelt precies dit patroon aan.
SharedFlow vs StateFlow: het juiste type kiezen voor events
De klassieke valstrikvraag luidt: "kan StateFlow eenmalige events leveren?" Het eerlijke antwoord is nee, niet veilig. Omdat StateFlow conflateert en ontdubbelt, kan een navigatie-event bij snelle updates verloren gaan, en het vuurt opnieuw af bij een configuratiewijziging omdat een nieuwe collector de bewaarde waarde opnieuw afspeelt. SharedFlow met replay = 0 lost beide op: er wordt niets bewaard, en elke emissie bereikt alleen de collectors die actief zijn op het moment van uitzenden.
class CheckoutViewModel : ViewModel() {
// replay = 0: a late collector must NOT re-receive a past navigation event.
private val _events = MutableSharedFlow<CheckoutEvent>(replay = 0)
val events: SharedFlow<CheckoutEvent> = _events.asSharedFlow()
fun onPaymentConfirmed() {
viewModelScope.launch {
// emit() suspends if the buffer is full; tryEmit() is the non-suspending variant.
_events.emit(CheckoutEvent.NavigateToReceipt)
}
}
}Voor architectuurvragen komt de diepere redenering achter het scheiden van state en events terug in de vergelijking MVVM vs MVI, waar MVI events als een expliciete stream behandelt in plaats van als mutable state.
Een cold Flow omzetten naar een hot StateFlow met stateIn
Interviewers vragen vaak hoe je de cold flow van een repository omzet naar UI-state. Het antwoord is stateIn (voor één bewaarde waarde) of shareIn (voor een broadcast zonder huidige waarde). De parameter SharingStarted bepaalt wanneer de upstream actief is, en WhileSubscribed(5_000) is de standaardkeuze omdat het de flow in leven houdt tijdens een rotatie zonder deze te lekken wanneer het scherm sluit.
val profile: StateFlow<Profile> = repo.profileStream()
.stateIn(
scope = viewModelScope,
// Keep the upstream alive 5s after the last collector leaves, surviving rotation.
started = SharingStarted.WhileSubscribed(5_000),
initialValue = Profile.EMPTY
)Het verschil tussen stateIn en shareIn is precies het verschil tussen StateFlow en SharedFlow: stateIn heeft een initialValue nodig en houdt state vast, terwijl shareIn een replay-aantal aanneemt en broadcast. Het bredere coroutinesmodel doornemen in deze gids om Kotlin-coroutines onder de knie te krijgen helpt om deze operators te koppelen aan scopes en cancellation.
Klaar om je Android gesprekken te halen?
Oefen met onze interactieve simulatoren, flashcards en technische tests.
Flows veilig verzamelen binnen de Android-lifecycle
Een vraag op seniorniveau is hoe je een flow verzamelt zonder werk te lekken terwijl het scherm op de achtergrond staat. Verzamelen binnen een gewone launch blijft doorlopen wanneer de UI gestopt is, verspilt CPU en riskeert crashes. repeatOnLifecycle(STARTED) annuleert het verzamelen bij STOP en herstart het bij START.
viewLifecycleOwner.lifecycleScope.launch {
// Collection restarts on STARTED and cancels on STOPPED: no wasted work in the background.
viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
viewModel.uiState.collect { state -> render(state) }
}
}In Jetpack Compose is collectAsStateWithLifecycle() het equivalent, dat stopt met verzamelen wanneer de app naar de achtergrond gaat en hervat bij terugkeer.
@Composable
fun ProfileScreen(viewModel: ProfileViewModel) {
// collectAsStateWithLifecycle stops collecting when the app is backgrounded.
val state by viewModel.uiState.collectAsStateWithLifecycle()
ProfileContent(state)
}Dit lifecyclebewustzijn is de reden dat StateFlow gecombineerd met collectAsStateWithLifecycle het standaard state-patroon is in moderne Compose-apps, iets wat verder aan bod komt in deze Jetpack Compose-interviewvragen.
StateFlow- en SharedFlow-emissies testen
Bij testen onderscheiden seniorkandidaten zich. De naïeve aanpak leest stateFlow.value één keer uit, maar dat mist tussenliggende states en kan een SharedFlow helemaal niet observeren. Het standaardantwoord noemt de Turbine-library, die suspendt totdat elke emissie binnenkomt en de test laat falen als een verwachte waarde nooit komt.
@Test
fun `emits Loading then Success on query`() = runTest {
val viewModel = SearchViewModel(fakeRepo)
viewModel.uiState.test {
assertEquals(SearchUiState.Idle, awaitItem()) // initial value
viewModel.onQueryChanged("kotlin")
assertEquals(SearchUiState.Loading, awaitItem()) // intermediate state
assertEquals(SearchUiState.Success(fakeResults), awaitItem())
cancelAndIgnoreRemainingEvents()
}
}Turbine combineren met runTest en een test dispatcher houdt de assertions deterministisch, en het noemen van StandardTestDispatcher versus UnconfinedTestDispatcher verraadt echte ervaring met het testen van coroutines.
Veelvoorkomende vervolgvragen over Kotlin Flow
Interviewers sluiten af met snelle controlevragen. Wat doet SharingStarted.WhileSubscribed(5_000)? Het start de upstream bij de eerste subscriber en stopt deze 5 seconden nadat de laatste zich afmeldt, lang genoeg om een rotatie te overleven. Waarom slaat StateFlow dubbele waarden over? Het vergelijkt met equals(), dus een gelijke waarde uitzenden is een no-op, en juist daarom zijn data classes belangrijk voor state. Kan SharedFlow zich gedragen als StateFlow? replay = 1 instellen laat het de laatste waarde bewaren, maar het mist nog steeds een synchrone .value en ontdubbelt nooit. Wat regelt de back-pressure op een SharedFlow? De parameters extraBufferCapacity en onBufferOverflow, waarbij BufferOverflow.DROP_OLDEST een gangbare keuze is voor events. Meer oefening met deze operators is te vinden in de interviewmodule over Kotlin-coroutines en Flow.
StateFlow gebruiken voor navigatie- of snackbar-events. Omdat het zijn laatste waarde opnieuw afspeelt naar nieuwe collectors, vuurt het event na een rotatie opnieuw af en wordt de gebruiker twee keer genavigeerd. Grijp naar SharedFlow met replay = 0, of modelleer een eenmalig event dat na afhandeling wordt gewist.
De broncode van kotlinx.coroutines en de referentie van het flow-package op GitHub zijn het waard om voor een interview door te nemen, aangezien de KDoc bij StateFlow en SharedFlow de conflatie- en replaygaranties precies beschrijft.
Conclusie
Het onderscheid Kotlin Flow vs StateFlow vs SharedFlow beloont precies taalgebruik in een interview. De belangrijkste punten om mee te nemen:
Flowis cold: de producer draait opnieuw voor elke collector, waardoor het past bij datapijplijnen op aanvraag.StateFlowis hot, houdt altijd een waarde vast en conflateert en ontdubbelt, wat het de tool voor UI-state maakt.SharedFlowis hot zonder verplichte beginwaarde, wat het de juiste keuze maakt voor eenmalige events.- Zet cold om naar hot met
stateInofshareIn, en gebruikSharingStarted.WhileSubscribed(5_000)om een rotatie te overleven. - Verzamel met
repeatOnLifecycle(STARTED)ofcollectAsStateWithLifecycle()om achtergrondwerk en lekken te voorkomen. - Lever events nooit via StateFlow: het replaygedrag vuurt ze opnieuw af na een configuratiewijziging.
Begin met oefenen!
Test je kennis met onze gespreksimulatoren en technische tests.
Tags
Delen
Gerelateerde artikelen

Kotlin 2.3 voor Android: Naamgebaseerde Destructurering, KMP en Sollicitatievragen 2026
Kotlin 2.3 sollicitatievragen over naamgebaseerde destructurering, Kotlin Multiplatform, contextparameters, coroutines en Flow. Voorbereiding op Android-ontwikkelaarsgesprekken in 2026 met praktische codevoorbeelden.

De 20 meest gestelde Jetpack Compose interviewvragen in 2026
De 20 meest gestelde Jetpack Compose interviewvragen: recomposition, state management, navigatie, performance en architectuurpatronen.

Kotlin Coroutines voor Android: Complete Gids 2026
Uitgebreide gids over Kotlin coroutines voor Android-ontwikkeling: suspend-functies, scopes, dispatchers, Flow en geavanceerde patronen.