Kotlin Flow vs StateFlow vs SharedFlow: Pertanyaan Interview Android 2026
Pertanyaan Kotlin Flow vs StateFlow vs SharedFlow yang diajukan pewawancara Android pada 2026, dengan jawaban jelas, tabel perbandingan, dan kode siap produksi.

Kotlin Flow vs StateFlow vs SharedFlow merupakan salah satu topik interview Android yang paling sering muncul pada 2026, dan mencampuradukkan ketiganya adalah cara tercepat untuk gagal di sesi coroutines. StateFlow dan SharedFlow sama-sama merupakan hot stream yang dibangun di atas Flow, tetapi keduanya hadir untuk menyelesaikan masalah yang berbeda: menyimpan state versus menyiarkan event. Pertanyaan-pertanyaan berikut adalah yang benar-benar diajukan pewawancara Android, lengkap dengan jawaban yang tepat serta kode siap produksi.
Sebuah Flow bersifat cold dan menjalankan produsernya sekali untuk setiap collector. StateFlow adalah stream hot yang di-conflate dan selalu menyimpan satu nilai terkini, ideal untuk UI state. SharedFlow adalah stream hot tanpa nilai awal wajib, ideal untuk event sekali pakai seperti navigasi atau snackbar.
Kotlin Flow vs StateFlow vs SharedFlow: perbedaan utama
StateFlow dan SharedFlow adalah spesialisasi dari SharedFlow, yang pada dirinya sendiri merupakan Flow yang hot. Perbedaan yang biasa digali pewawancara adalah cold versus hot, apakah nilai terkini dipertahankan, dan bagaimana masing-masing berperilaku terhadap emisi duplikat. Model mental yang ringkas: Flow adalah resep, StateFlow adalah satu nilai mutable, dan SharedFlow adalah event bus.
| Properti | Flow (cold) | StateFlow | SharedFlow |
|---|---|---|---|
| Temperatur | Cold | Hot | Hot |
| Nilai awal | Tidak ada | Wajib | Opsional (via replay) |
| Menyimpan nilai terkini | Tidak | Ya, via .value | Tidak |
| Memancarkan duplikat | Ya | Tidak (conflated + dedup) | Dapat dikonfigurasi |
| Collector tambahan | Stream baru setiap kali | Dibagikan | Dibagikan |
| Paling cocok untuk | Pipeline data async | UI state | Event sekali pakai |
Dokumentasi resmi Kotlin coroutines memperlakukan perilaku cold-by-default ini sebagai properti yang mendefinisikan Flow, sehingga jawaban yang kuat dimulai dari sana.
Mengapa Kotlin Flow bersifat cold secara default?
Sebuah cold flow tidak melakukan apa pun sampai collect() dipanggil, dan ia mengeksekusi ulang blok produsernya untuk setiap collector. Dua collector pada cold flow yang sama memicu dua panggilan jaringan yang independen. Ini adalah konsep yang paling sering diuji, sehingga sebuah contoh singkat memperkuat jawaban.
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
}Karena produser dijalankan ulang untuk setiap collector, cold flow adalah default yang tepat untuk pipeline data yang seharusnya berjalan sesuai permintaan. Ini baru menjadi masalah ketika sebuah nilai harus dibagikan ke seluruh layar, dan di titik itulah StateFlow serta SharedFlow berperan.
Pertanyaan interview StateFlow: state yang selalu memancarkan nilai
StateFlow adalah flow hot yang selalu memiliki nilai dan memutar ulang (replay) nilai terbaru tersebut ke setiap collector baru. Ia membutuhkan nilai awal, mengekspos .value untuk pembacaan sinkron, serta meng-conflate emisi: pembaruan cepat yang beruntun bisa melewatkan nilai-nilai antara, dan menyetel nilai yang sama dua kali tidak memancarkan apa pun karena StateFlow melakukan deduplikasi melalui kesetaraan (equality). Hal ini menjadikannya pengganti modern untuk LiveData di dalam sebuah 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) }
}
}
}Pertanyaan lanjutan yang umum: mengapa mengekspos asStateFlow() alih-alih field mutable? Karena ia memberikan UI sebuah tampilan read-only sehingga state hanya bisa berubah melalui ViewModel, yang menjaga unidirectional data flow tetap utuh. Panduan StateFlow dan SharedFlow dari Android sendiri merekomendasikan pola persis seperti ini.
SharedFlow vs StateFlow: memilih tipe yang tepat untuk event
Pertanyaan jebakan klasiknya adalah "apakah StateFlow bisa mengirimkan event sekali pakai?" Jawaban jujurnya tidak, tidak dengan aman. Karena StateFlow meng-conflate dan melakukan deduplikasi, sebuah event navigasi bisa hilang saat terjadi pembaruan cepat, dan ia terpicu ulang saat configuration change karena collector baru memutar ulang nilai yang tersimpan. SharedFlow dengan replay = 0 mengatasi keduanya: tidak ada yang disimpan, dan setiap emisi hanya menjangkau collector yang aktif pada saat emisi.
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)
}
}
}Untuk pertanyaan seputar arsitektur, alasan yang lebih mendalam di balik pemisahan state dari event muncul dalam perbandingan MVVM vs MVI, di mana MVI memperlakukan event sebagai stream eksplisit alih-alih mutable state.
Mengubah cold Flow menjadi hot StateFlow dengan stateIn
Pewawancara sering menanyakan cara mengubah cold flow dari sebuah repository menjadi UI state. Jawabannya adalah stateIn (untuk satu nilai yang dipertahankan) atau shareIn (untuk broadcast tanpa nilai terkini). Parameter SharingStarted mengontrol kapan upstream aktif, dan WhileSubscribed(5_000) adalah pilihan standar karena ia menjaga flow tetap hidup saat rotasi tanpa membiarkannya bocor ketika layar ditutup.
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
)Perbedaan antara stateIn dan shareIn persis sama dengan perbedaan antara StateFlow dan SharedFlow: stateIn membutuhkan initialValue dan menyimpan state, sedangkan shareIn menerima jumlah replay dan melakukan broadcast. Meninjau model coroutines yang lebih luas dalam panduan menguasai Kotlin coroutines ini membantu menghubungkan operator-operator ini dengan scope dan cancellation.
Siap menguasai wawancara Android Anda?
Berlatih dengan simulator interaktif, flashcards, dan tes teknis kami.
Meng-collect flow dengan aman pada lifecycle Android
Pertanyaan tingkat senior adalah bagaimana meng-collect sebuah flow tanpa membocorkan pekerjaan ketika layar berada di background. Meng-collect di dalam launch biasa akan terus berjalan saat UI dihentikan, memboroskan CPU dan berisiko menyebabkan crash. repeatOnLifecycle(STARTED) membatalkan collection pada STOP dan menjalankannya kembali pada 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) }
}
}Di Jetpack Compose, padanannya adalah collectAsStateWithLifecycle(), yang berhenti meng-collect ketika aplikasi berada di background dan melanjutkannya kembali saat kembali ke depan.
@Composable
fun ProfileScreen(viewModel: ProfileViewModel) {
// collectAsStateWithLifecycle stops collecting when the app is backgrounded.
val state by viewModel.uiState.collectAsStateWithLifecycle()
ProfileContent(state)
}Kesadaran terhadap lifecycle inilah yang membuat StateFlow yang dipasangkan dengan collectAsStateWithLifecycle menjadi pola state default pada aplikasi Compose modern, sebuah poin yang dibahas lebih lanjut dalam pertanyaan interview Jetpack Compose ini.
Cara menguji emisi StateFlow dan SharedFlow
Pengujian adalah tempat kandidat senior menunjukkan perbedaannya. Pendekatan naif membaca stateFlow.value sekali saja, tetapi cara itu melewatkan state antara dan sama sekali tidak dapat mengamati SharedFlow. Jawaban standarnya menyebut library Turbine, yang menunda (suspend) hingga setiap emisi tiba dan menggagalkan tes jika nilai yang diharapkan tidak pernah muncul.
@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()
}
}Memasangkan Turbine dengan runTest dan sebuah test dispatcher menjaga assertion tetap deterministik, dan menyebut StandardTestDispatcher versus UnconfinedTestDispatcher menandakan pengalaman nyata dalam menguji coroutine.
Pertanyaan lanjutan interview Kotlin Flow yang umum
Pewawancara menutup dengan serangkaian pertanyaan cepat. Apa yang dilakukan SharingStarted.WhileSubscribed(5_000)? Ia memulai upstream saat subscriber pertama muncul dan menghentikannya 5 detik setelah subscriber terakhir berhenti, yang cukup lama untuk bertahan melewati rotasi. Mengapa StateFlow melewatkan nilai duplikat? Ia membandingkan dengan equals(), sehingga memancarkan nilai yang setara menjadi no-op, dan itulah alasan data class penting untuk state. Apakah SharedFlow bisa berperilaku seperti StateFlow? Menyetel replay = 1 membuatnya menahan nilai terakhir, tetapi ia tetap tidak memiliki .value yang sinkron dan tidak pernah melakukan deduplikasi. Apa yang mengontrol back-pressure pada SharedFlow? Parameter extraBufferCapacity dan onBufferOverflow, dengan BufferOverflow.DROP_OLDEST sebagai pilihan umum untuk event. Latihan yang lebih mendalam tentang operator-operator ini tersedia dalam modul interview Kotlin coroutines dan Flow.
Menggunakan StateFlow untuk event navigasi atau snackbar. Karena ia memutar ulang nilai terakhirnya ke collector baru, event tersebut terpicu ulang setelah rotasi dan pengguna dinavigasikan dua kali. Gunakan SharedFlow dengan replay = 0, atau modelkan sebuah event sekali pakai yang dibersihkan setelah ditangani.
Kode sumber kotlinx.coroutines beserta referensi paket flow-nya di GitHub layak dibaca sekilas sebelum interview, karena KDoc pada StateFlow dan SharedFlow menyatakan jaminan conflation dan replay secara tepat.
Kesimpulan
Perbedaan antara Kotlin Flow vs StateFlow vs SharedFlow menghargai penggunaan bahasa yang tepat saat interview. Poin-poin utama yang perlu dibawa:
Flowbersifat cold: produser dijalankan ulang untuk setiap collector, sehingga cocok untuk pipeline data sesuai permintaan.StateFlowbersifat hot, selalu menyimpan nilai, serta meng-conflate dan melakukan deduplikasi, menjadikannya alat untuk UI state.SharedFlowbersifat hot tanpa nilai awal wajib, menjadikannya pilihan yang tepat untuk event sekali pakai.- Ubah cold menjadi hot dengan
stateInataushareIn, dan gunakanSharingStarted.WhileSubscribed(5_000)agar bertahan melewati rotasi. - Collect dengan
repeatOnLifecycle(STARTED)ataucollectAsStateWithLifecycle()untuk menghindari pekerjaan di background dan kebocoran. - Jangan pernah mengirimkan event melalui StateFlow: perilaku replay-nya akan memicunya ulang setelah configuration change.
Mulai berlatih!
Uji pengetahuan Anda dengan simulator wawancara dan tes teknis kami.
Tag
Bagikan
Artikel terkait

Kotlin 2.3 untuk Android: Name-Based Destructuring, KMP dan Pertanyaan Wawancara 2026
Pertanyaan wawancara Kotlin 2.3 untuk developer Android di tahun 2026. Name-based destructuring, KMP, context parameters, Flow, dan coroutines dengan contoh kode.

20 Pertanyaan Wawancara Jetpack Compose Teratas di Tahun 2026
20 pertanyaan wawancara Jetpack Compose yang paling sering ditanyakan: recomposition, state management, navigation, performa, dan pola arsitektur dengan contoh kode lengkap.

Menguasai Kotlin Coroutines: Panduan Lengkap 2026
Pelajari Kotlin coroutines untuk pengembangan Android: suspend function, scope, dispatcher, dan pola-pola tingkat lanjut.