# Kotlin Flow, StateFlow ve SharedFlow: 2026'da Android Mülakat Soruları > Android mülakatçılarının 2026'da sorduğu Kotlin Flow, StateFlow ve SharedFlow soruları; net yanıtlar, bir karşılaştırma tablosu ve üretime hazır kod ile birlikte. - Published: 2026-07-01 - Updated: 2026-07-07 - Author: SharpSkill - Tags: android, kotlin, coroutines, flow, interview - Reading time: 9 min --- Kotlin Flow, StateFlow ve SharedFlow, 2026'da Android mülakatlarının en sık karşılaşılan konularından biridir ve üçünü birbirine karıştırmak, bir coroutine turunu kaybetmenin en hızlı yoludur. StateFlow ve SharedFlow, Flow üzerine inşa edilmiş sıcak (hot) akışlardır, ancak farklı problemleri çözmek için vardır: durum tutmak ile olay yayınlamak. Aşağıdaki sorular, Android mülakatçılarının gerçekten sorduğu sorulardır; kesin yanıtlar ve üretime hazır kod ile birlikte sunulmuştur. > **20 saniyelik yanıt** > > Bir `Flow` soğuktur (cold) ve üreticisini her collector için bir kez çalıştırır. `StateFlow` ise sıcak, birleştirilmiş (conflated) bir akıştır ve her zaman tek bir güncel değer tutar; UI durumu için idealdir. `SharedFlow`, zorunlu bir başlangıç değeri olmayan sıcak bir akıştır ve navigasyon ya da snackbar gibi tek seferlik olaylar için idealdir. ## Kotlin Flow, StateFlow ve SharedFlow: temel farklar StateFlow ve SharedFlow, kendisi de sıcak bir `Flow` olan `SharedFlow`'un özelleşmiş halleridir. Mülakatçıların araştırdığı ayrım şudur: akış soğuk mu sıcak mı, güncel bir değer saklanıyor mu ve her biri yinelenen yayınlarda (duplicate emissions) nasıl davranıyor. Kısa bir zihinsel model: `Flow` bir tariftir, `StateFlow` tek bir değiştirilebilir değerdir ve `SharedFlow` bir olay veri yoludur (event bus). | Özellik | Flow (soğuk) | StateFlow | SharedFlow | |---|---|---|---| | Sıcaklık | Soğuk | Sıcak | Sıcak | | Başlangıç değeri | Yok | Zorunlu | İsteğe bağlı (`replay` ile) | | Güncel değeri tutar | Hayır | Evet, `.value` ile | Hayır | | Yinelenenleri yayınlar | Evet | Hayır (birleştirilir + tekilleştirilir) | Yapılandırılabilir | | Ek collector'lar | Her seferinde yeni akış | Paylaşımlı | Paylaşımlı | | En uygun | Asenkron veri hatları | UI durumu | Tek seferlik olaylar | [Resmi Kotlin coroutines dokümantasyonu](https://kotlinlang.org/docs/flow.html), bu varsayılan olarak soğuk olma davranışını `Flow`'un tanımlayıcı özelliği olarak ele alır; bu yüzden güçlü bir yanıt buradan başlar. ## Bir Kotlin Flow neden varsayılan olarak soğuktur? Soğuk bir flow, `collect()` çağrılana kadar hiçbir şey yapmaz ve üretici bloğunu her collector için yeniden çalıştırır. Aynı soğuk flow üzerindeki iki collector, iki bağımsız ağ çağrısını tetikler. Bu, en çok test edilen tek kavramdır; bu yüzden kısa bir örnek yanıtı sağlamlaştırır. ```kotlin // SearchRepository.kt fun searchResults(query: String): Flow> = 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 } ``` Üretici her collector için yeniden başladığından, soğuk flow'lar talep üzerine çalışması gereken veri hatları için doğru varsayılandır. Yalnızca bir değerin tüm ekran boyunca paylaşılması gerektiğinde sorun haline gelirler; tam da StateFlow ile SharedFlow'un devreye girdiği nokta budur. ## StateFlow mülakat soruları: her zaman yayın yapan durum `StateFlow`, her zaman bir değere sahip olan ve bu en son değeri her yeni collector'a yeniden gönderen (replay) sıcak bir flow'dur. Bir başlangıç değeri gerektirir, senkron okumalar için `.value` sunar ve yayınları birleştirir (conflate): hızlı ardışık güncellemeler ara değerleri atlayabilir ve aynı değeri iki kez atamak hiçbir şey yayınlamaz, çünkü eşitlik (equality) üzerinden tekilleştirme yapar. Bu da onu bir `ViewModel` içindeki `LiveData`'nın modern alternatifi haline getirir. ```kotlin // SearchViewModel.kt 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.Idle) val uiState: StateFlow = _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) } } } } ``` Sık gelen bir devam sorusu: neden değiştirilebilir alan yerine `asStateFlow()` açığa çıkarılır? Bu, UI'a yalnızca okunabilir bir görünüm verir; böylece durum yalnızca ViewModel üzerinden değişebilir ve tek yönlü veri akışı bozulmadan korunur. Android'in kendi [StateFlow ve SharedFlow rehberi](https://developer.android.com/kotlin/flow/stateflow-and-sharedflow) tam olarak bu deseni önerir. ## SharedFlow vs StateFlow: olaylar için doğru türü seçmek Klasik tuzak soru şudur: "StateFlow tek seferlik olaylar iletebilir mi?" Dürüst yanıt hayırdır, en azından güvenli bir şekilde iletemez. StateFlow birleştirdiği ve tekilleştirdiği için, bir navigasyon olayı hızlı güncellemeler altında düşürülebilir; ayrıca yapılandırma değişikliğinde yeniden tetiklenir, çünkü yeni bir collector saklanan değeri yeniden gönderir. `replay = 0` ile `SharedFlow` her ikisini de çözer: hiçbir şey saklanmaz ve her yayın yalnızca yayın anında aktif olan collector'lara ulaşır. ```kotlin // CheckoutViewModel.kt class CheckoutViewModel : ViewModel() { // replay = 0: a late collector must NOT re-receive a past navigation event. private val _events = MutableSharedFlow(replay = 0) val events: SharedFlow = _events.asSharedFlow() fun onPaymentConfirmed() { viewModelScope.launch { // emit() suspends if the buffer is full; tryEmit() is the non-suspending variant. _events.emit(CheckoutEvent.NavigateToReceipt) } } } ``` Mimari sorularında, durumu olaylardan ayırmanın ardındaki daha derin gerekçe [MVVM vs MVI karşılaştırmasında](/blog/android/mvvm-vs-mvi-architecture) ortaya çıkar; burada MVI, olayları değiştirilebilir durum yerine açık bir akış olarak ele alır. ## stateIn ile soğuk bir Flow'u sıcak bir StateFlow'a dönüştürmek Mülakatçılar sıklıkla bir repository'nin soğuk flow'unun UI durumuna nasıl dönüştürüleceğini sorar. Yanıt, `stateIn` (tek bir saklanan değer için) veya `shareIn` (güncel değeri olmayan bir yayın için) kullanmaktır. `SharingStarted` parametresi upstream'in ne zaman aktif olacağını denetler ve `WhileSubscribed(5_000)` standart seçimdir, çünkü flow'u bir ekran döndürme boyunca canlı tutarken ekran kapandığında sızdırmaz. ```kotlin // ProfileViewModel.kt val profile: StateFlow = 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 ) ``` `stateIn` ile `shareIn` arasındaki fark, tam olarak StateFlow ile SharedFlow arasındaki farktır: `stateIn` bir `initialValue` gerektirir ve durum tutar, `shareIn` ise bir `replay` sayısı alır ve yayın yapar. Daha geniş coroutine modelini [Kotlin coroutine'lerinde ustalaşma rehberinde](/blog/android/mastering-kotlin-coroutines) gözden geçirmek, bu operatörleri kapsamlar (scope) ve iptal (cancellation) ile ilişkilendirmeye yardımcı olur. ## Android yaşam döngüsünde flow'ları güvenli şekilde toplamak Kıdemli seviye bir soru, ekran arka plandayken işi sızdırmadan bir flow'un nasıl toplanacağıdır. Düz bir `launch` içinde toplama yapmak, UI durdurulduğunda çalışmaya devam eder; bu da CPU'yu boşa harcar ve çökme riski yaratır. `repeatOnLifecycle(STARTED)`, toplamayı `STOP` anında iptal eder ve `START` anında yeniden başlatır. ```kotlin // ProfileFragment.kt (View system) 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) } } } ``` Jetpack Compose'da bunun karşılığı `collectAsStateWithLifecycle()`'dır; uygulama arka plana alındığında toplamayı durdurur ve geri dönüldüğünde devam ettirir. ```kotlin // ProfileScreen.kt (Jetpack Compose) @Composable fun ProfileScreen(viewModel: ProfileViewModel) { // collectAsStateWithLifecycle stops collecting when the app is backgrounded. val state by viewModel.uiState.collectAsStateWithLifecycle() ProfileContent(state) } ``` Bu yaşam döngüsü farkındalığı, `collectAsStateWithLifecycle` ile eşleştirilmiş StateFlow'un modern Compose uygulamalarında neden varsayılan durum deseni olduğunu açıklar; bu konu şu [Jetpack Compose mülakat sorularında](/blog/android/jetpack-compose-interview-questions) daha ayrıntılı ele alınır. ## StateFlow ve SharedFlow yayınları nasıl test edilir Kıdemli adaylar kendilerini test yazımında ayrıştırır. Naif yaklaşım `stateFlow.value`'yu bir kez okur, ancak bu ara durumları kaçırır ve bir SharedFlow'u hiç gözlemleyemez. Standart yanıt, her yayın gelene kadar bekleyen (suspend eden) ve beklenen bir değer hiç gelmezse testi başarısız kılan Turbine kütüphanesini anar. ```kotlin // SearchViewModelTest.kt @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'i `runTest` ve bir test dispatcher'ı ile birleştirmek, doğrulamaları belirlenimci (deterministic) tutar; `StandardTestDispatcher` ile `UnconfinedTestDispatcher` arasındaki farktan söz etmek ise gerçek coroutine test deneyimini gösterir. ## Sık gelen Kotlin Flow mülakat devam soruları Mülakatçılar seri sorularla kapanış yapar. `SharingStarted.WhileSubscribed(5_000)` ne yapar? Upstream'i ilk aboneyle başlatır ve son abone ayrıldıktan 5 saniye sonra durdurur; bu süre bir ekran döndürmeyi atlatmaya yetecek kadar uzundur. StateFlow neden yinelenen değerleri atlar? `equals()` ile karşılaştırma yapar, dolayısıyla eşit bir değer yayınlamak işlemsizdir (no-op); durum için data class'ların önemli olmasının nedeni budur. SharedFlow, StateFlow gibi davranabilir mi? `replay = 1` ayarlamak son değeri tutmasını sağlar, ancak yine de senkron bir `.value`'dan yoksundur ve asla tekilleştirme yapmaz. SharedFlow üzerindeki geri baskıyı (back-pressure) ne denetler? `extraBufferCapacity` ve `onBufferOverflow` parametreleri; olaylar için `BufferOverflow.DROP_OLDEST` sık tercih edilen bir seçenektir. Bu operatörler üzerinde daha derin pratik, [Kotlin coroutines ve Flow mülakat modülünde](/technologies/android/interview-questions/android-kotlin-coroutines-flow) yer alır. > **Adayları eleyen hata** > > Navigasyon veya snackbar olayları için `StateFlow` kullanmak. Son değerini yeni collector'lara yeniden gönderdiği için, olay bir ekran döndürmeden sonra yeniden tetiklenir ve kullanıcı iki kez yönlendirilir. Bunun yerine `replay = 0` ile `SharedFlow` tercih edilmeli ya da işlendikten sonra temizlenen tek seferlik bir olay modellenmelidir. kotlinx.coroutines kaynak kodu ve onun [GitHub'daki flow paketi referansı](https://github.com/Kotlin/kotlinx.coroutines/tree/master/kotlinx-coroutines-core) bir mülakattan önce göz atmaya değer, çünkü `StateFlow` ve `SharedFlow` üzerindeki KDoc, birleştirme (conflation) ve replay garantilerini tam olarak belirtir. ## Sonuç Kotlin Flow, StateFlow ve SharedFlow ayrımı, bir mülakatta kesin dili ödüllendirir. Bir mülakata taşınabilecek temel çıkarımlar: - `Flow` soğuktur: üretici her collector için yeniden çalışır, bu yüzden talep üzerine çalışan veri hatlarına uygundur. - `StateFlow` sıcaktır, her zaman bir değer tutar ve hem birleştirir hem tekilleştirir; bu da onu UI durumu için doğru araç yapar. - `SharedFlow` sıcaktır ve zorunlu bir başlangıç değeri yoktur; bu da onu tek seferlik olaylar için doğru seçim yapar. - Soğuktan sıcağa geçiş `stateIn` ya da `shareIn` ile yapılır ve rotasyonu atlatmak için `SharingStarted.WhileSubscribed(5_000)` kullanılır. - Arka plan işini ve sızıntıları önlemek için toplama `repeatOnLifecycle(STARTED)` ya da `collectAsStateWithLifecycle()` ile yapılır. - Olaylar asla StateFlow üzerinden iletilmemelidir: replay davranışı, bir yapılandırma değişikliğinden sonra onları yeniden tetikler. --- Source: SharpSkill (https://sharpskill.dev), tech interview preparation for your real stack. HTML version of this page: https://sharpskill.dev/tr/blog/android/kotlin-flow-vs-stateflow-vs-sharedflow-interview