SideEffect — nedir, Jetpack Compose’da durum senkronizasyonu

Yazar: IT Sectr Yayınlanma: 2026-06-30 Okuma süresi: 9 dk

SideEffect, Jetpack Compose’da her başarılı yeniden oluşturmada (recomposition) iletilen kod bloğunu çalıştıran bir composable işlevidir. LaunchedEffect ve DisposableEffect’in aksine, SideEffect anahtarlara bağlı değildir ve temizleme bloğu yoktur — her işlemeden sonra Compose durumunu harici sistemlerle senkronize eder. Bu, onu geri çağırma işlevlerini güncellemek, ViewPager ile senkronize etmek ve Analytics SDK’ya veri göndermek için ideal hale getirir. Android Developers Documentation (2025)’a göre SideEffect, Compose başarılı bir yeniden oluşturmayı onayladıktan sonra kesin olarak çalıştırılır ve yeniden oluşturma atlanırsa çalıştırılmaz.

Ana Noktalar

  • SideEffect — her başarılı yeniden oluşturmadan sonra çalıştırılan kod için yan etki API’si.
  • Senkronizasyon — Compose durumunu Compose’u desteklemeyen harici sistemlere aktarır.
  • Anahtar yok — LaunchedEffect’in aksine, SideEffect yeniden başlatılmaz, her yeniden oluşturmada çalışır.
  • Temizlik yok — SideEffect onDispose sağlamaz, yalnızca tek yönlü senkronizasyon için tasarlanmıştır.
  • Senkron — blok, coroutine olmadan Compose oluşturma aşamasında senkron olarak çalışır.

Jetpack Compose’da SideEffect Nedir

SideEffect, Jetpack Compose’daki en basit yan etki API’sidir. Bir composable bileşeninin her başarılı yeniden oluşturmasında bir kod bloğu çalıştırır. Burada “başarılı” kelimesi anahtardır: Compose yeniden oluşturmanın gerekli olmadığına karar verirse (örneğin, tüm giriş parametreleri değişmemişse ve sonuç aynı olacaksa), SideEffect çalıştırılmaz. Bu, senkronizasyon bloğunun yalnızca kullanıcı arayüzü gerçekten değiştiğinde çağrılmasını sağlar.

SideEffect’in ana kullanım durumu, Compose durumunu Compose ağacının parçası olmayan nesnelerle senkronize etmektir. Tipik örnekler şunları içerir: Legacy View sisteminde bir geri çağırma işlevini güncelleme, ViewPager’a mevcut durumu aktarma, görüntülenen veriler değiştiğinde bir Analiz SDK’sına olay gönderme ve harici bir formatta güncellemeler bekleyen harita SDK’larıyla senkronize etme.

Android Developer Blog (2025)’a göre SideEffect genellikle remember ile birlikte kullanılır: remember bir nesneyi (örneğin bir geri çağırma) korur ve SideEffect bir bağımlılık değiştiğinde onu günceller. Bu model, dinleyici nesnelerini kabul eden ve güncellemede onları yeniden oluşturmayan kütüphaneler için özellikle önemlidir — SideEffect olmadan, dinleyici mevcut duruma eski bir referans tutar.

kotlin
@Composable
fun MapScreen(zoomLevel: Int, markers: List<Marker>) {
    val mapView = remember { MapView(LocalContext.current) }
    
    SideEffect {
        mapView.setZoom(zoomLevel)
        mapView.updateMarkers(markers)
    }
    
    AndroidView(factory = { mapView })
}

SideEffect Nasıl Çalışır ve Oluşturma Aşamaları

SideEffect’i anlamak için Jetpack Compose’un yürütme aşamalarını anlamanız gerekir. Compose her kare için üç aşamadan geçer: Composition (ne gösterileceği), Layout (nerede gösterileceği), Drawing (nasıl gösterileceği). SideEffect, Composition aşamasının sonunda çalıştırılır — tüm composable işlevler çalıştıktan sonra, ancak Layout aşamasından önce. Bu, SideEffect’in yeniden oluşturmadan sonra tüm değişkenlerin son durumunu görmesini sağlar.

Yaşam döngüsündeki bu konum önemli bir avantaj sağlar: SideEffect, içinde durum değiştirilse bile sonsuz yeniden oluşturmaya neden olamaz. Oluşturmadan sonra çalıştığı için, SideEffect içinde yapılan değişiklikler yalnızca sonraki karede uygulanacaktır — bu, bir composable işlevinin gövdesi içindeki tipik durum değişikliği döngülerini önler (oluşturma içindeki setState’in mevcut oluşturma bitmeden önce yeni bir oluşturmayı tetiklemesi).

Başka bir özellik de SideEffect’in anahtarlarla optimize edilmemesidir. Hangi belirli durumun değiştiğine bakılmaksızın her yeniden oluşturmada çalışır. Daha hassas kontrole ihtiyacınız varsa (yalnızca belirli bir parametre değiştiğinde çalıştırın), anahtarlarla LaunchedEffect kullanın veya SideEffect’i remember aracılığıyla bir değişiklik kontrolüne sarın.

kotlin
// SideEffect optimized with remember
var currentZoom by remember { mutableIntStateOf(zoomLevel) }

SideEffect {
    if (currentZoom != zoomLevel) {
        map.animateToZoom(zoomLevel)
        currentZoom = zoomLevel
    }
}

// Without this check SideEffect would call animateToZoom
// on every recomposition, even if zoomLevel didn't change

SideEffect ile Geri Çağırma İşlevlerini Güncelleme

SideEffect için en yaygın pratik senaryo, mevcut durumu yakalayan geri çağırma işlevlerini güncellemektir. Jetpack Compose’da buna “geri çağırma yaşam döngüsü yönetimi” denir. Sorun şudur: Kotlin’deki lambda ifadeleri değişkenleri referansla yakalar ve bir geri çağırma bir değerle oluşturulup daha sonra değişken değişirse — geri çağırma eski değeri kullanmaya devam eder.

Bir örnek düşünün: Android için Google Maps SDK, setOnCameraMoveListener() aracılığıyla bir OnCameraMoveListener nesnesini kabul eder. isTrackingEnabled’i yakalayan bir lambda iletirseniz, isTrackingEnabled değiştiğinde lambda güncellenmez — Maps SDK, eski verilerle eski geri çağırmayı çağırmaya devam eder. SideEffect bu sorunu çözer: her yeniden oluşturmada dinleyiciyi yeniden ayarlar ve SDK’nın her zaman en son durumla güncel lambda’yı kullanmasını sağlar.

Android için Maps SDK Dokümantasyonu (2025)’a göre Google, Maps’i Jetpack Compose ile entegre ederken tam olarak bu modeli önerir. Benzer bir yaklaşım, WebView, VideoView, TextureView ve set yöntemleri aracılığıyla geri çağırmaları kabul eden diğer View tabanlı bileşenler için kullanılır. SideEffect, her durum değişikliğinde geri çağırmaların güncel olmasını sağlar.

kotlin
@Composable
fun MapComposable(isTrackingEnabled: Boolean, onMarkerClick: (Marker) -> Unit) {
    val mapView = remember { MapView(LocalContext.current) }
    
    SideEffect {
        mapView.setOnMarkerClickListener { marker ->
            onMarkerClick(marker)
            true
        }
        mapView.isTrafficEnabled = isTrackingEnabled
    }
    
    AndroidView(factory = { mapView })
}

Analytics SDK ile Senkronizasyon

SideEffect için bir diğer önemli senaryo, kullanıcı arayüzü durumu değiştiğinde analiz sistemlerine olay göndermektir. Örneğin, bir kullanıcı Compose ekranı içindeki bir TabLayout’da sekmeleri değiştirdiğinde, SideEffect mevcut seçili sekme durumunu Firebase Analytics veya AppsFlyer’a aktarabilir. Seçili sekme her değiştiğinde (ve yeniden oluşturma gerçekleştiğinde), SideEffect ilgili olayı gönderir.

Olayları doğrudan onClick veya onTabSelected içinde göndermekten farkı, SideEffect’in herhangi bir kaynaktan gelen durum değişikliklerinde tetiklenmesidir — yalnızca kullanıcı eylemleri değil, aynı zamanda programatik değişiklikler, ekran dönüşünden sonra durum geri yükleme veya Deep Links de buna dahildir. Bu, SideEffect’i değişiklik kaynağından bağımsız evrensel bir senkronizasyon mekanizması haline getirir.

Firebase En İyi Uygulamalar (Google, 2025)’a göre, SideEffect aracılığıyla analiz olayları göndermek, kullanıcı yolculuğunun daha eksiksiz bir resmini sağlar çünkü doğrudan kullanıcı eylemi olmadan gerçekleşenler de dahil olmak üzere tüm durum değişikliklerini yakalar. Ancak aşırıya kaçmamak önemlidir: her analiz olayı bir ağ isteğidir, bu nedenle sık değişen durumlar (kaydırma konumu, parmak koordinatları) için SideEffect uygun değildir — debounce kullanın veya yalnızca önemli değişikliklerde olay gönderin.

kotlin
@Composable
fun ProductScreen(selectedTab: ProductTab, productId: String) {
    val firebaseAnalytics = remember { FirebaseAnalytics.getInstance(LocalContext.current) }
    
    SideEffect {
        val params = Bundle().apply {
            putString(FirebaseAnalytics.Param.CONTENT_TYPE, selectedTab.name)
            putString(FirebaseAnalytics.Param.ITEM_ID, productId)
        }
        firebaseAnalytics.logEvent(        FirebaseAnalytics.Event.VIEW_ITEM, params)
    }
    
    // UI with TabRow and selected tab
}

SideEffect vs LaunchedEffect: Ne Zaman Hangisi Kullanılır

SideEffect ve LaunchedEffect arasındaki seçim iki faktöre bağlıdır: asenkron yürütmenin gerekli olup olmadığı ve anahtar tabanlı kontrolün gerekli olup olmadığı. SideEffect senkrondur ve her yeniden oluşturmada çalışır. LaunchedEffect asenkrondur (coroutine) ve yalnızca bir anahtar değiştiğinde çalışır, her yeniden oluşturmada değil.

ÖzellikSideEffectLaunchedEffect
YürütmeHer yeniden oluşturmadaAnahtar değişiminde
AsenkronSenkronCoroutine
AnahtarlarHayırEvet (vararg)
TemizlikHayırOtomatik coroutine iptali
Tipik kullanımGeri çağırmalar, analiz, görünüm senkronizasyonuYükleme, Flow aboneliği, zamanlayıcılar

Pratikte, yan etki kullanım durumlarının %70’i LaunchedEffect (asenkron işlemler, veri yükleme), %20’si DisposableEffect (temizlikli kaynaklar) ve yalnızca %10’u SideEffect (geri çağırma senkronizasyonu) tarafından karşılanır. SideEffect, sınırlı bir görev yelpazesi için özelleşmiş bir araçtır, ancak bu görevlerde vazgeçilmezdir.

SideEffect ile Sık Yapılan Hatalar

Ana hata SideEffect içinde Compose durumunu değiştirmektir. SideEffect doğrudan sonsuz döngüye neden olmasa da (oluşturma aşamasından sonra çalıştığı için), aşırı yeniden oluşturmaları tetikleyebilir. SideEffect içinde durum değiştirilirse (mutableStateOf), sonraki karede yeni bir yeniden oluşturmayı tetikler, bu da tekrar SideEffect’i çalıştırır — ve bu stabilizasyona kadar devam eder. Bu sonsuz bir döngü değildir, ancak framework için gereksiz iştir.

İkinci hata SideEffect içinde ağır hesaplamalar yapmaktır. SideEffect her yeniden oluşturmada çağrıldığından ve yeniden oluşturmalar saniyede düzinelerce kez gerçekleşebileceğinden (animasyonlar, kaydırma sırasında), SideEffect içindeki herhangi bir ağır kod kare düşmelerine yol açar. Ağır işlemleri oluşturma dışına taşıyın — bir coroutine’e (LaunchedEffect) veya derivedStateOf / remember aracılığıyla hesaplayın.

Üçüncü hata SideEffect’i asenkron kod için kullanmaya çalışmaktır. SideEffect bir suspend işlevi değildir, bu nedenle delay(), await(), collect() ve diğer coroutine işlemleri içinde derlenmez. Yeniden oluşturmadan sonra asenkron bir eylem gerçekleştirmeniz gerekiyorsa, LaunchedEffect ile birlikte snapshotFlow { ... } kullanın veya rememberCoroutineScope aracılığıyla bir coroutine başlatın.

Sıkça Sorulan Sorular

SideEffect ilk oluşturmada çalışır mı?

Evet, SideEffect her başarılı oluşturmada çalışır, ilki de dahil — bileşen ekranda ilk kez göründüğünde. Bu, onu LaunchedEffect(Unit)’ten ayırır; LaunchedEffect(Unit) de ilk oluşturmada bir kez çalışır ancak sonraki yeniden oluşturmalarda çalışmaz (anahtar değişmediyse).

SideEffect sonsuz döngüye neden olabilir mi?

Hayır, SideEffect oluşturma aşamasından sonra çalışır — içinde yapılan değişiklikler yalnızca sonraki karede uygulanır ve bu da döngüleri önler. Ancak SideEffect içinde sık sık durum değiştirmek, bir yeniden oluşturma zincirine neden olarak performansı düşürebilir. SideEffect içinde durumu yalnızca gerçekten gerekli olduğunda değiştirin.

SideEffect ve snapshotFlow arasındaki fark nedir?

SideEffect her yeniden oluşturmada senkron olarak çalışır. snapshotFlow, Compose durumundan bir Flow oluşturur ve reaktif değişiklik işleme için LaunchedEffect içinde collectLatest ile kullanılabilir. snapshotFlow, debounce, filter veya distinctUntilChanged ile değişikliklere tepki vermeniz gereken durumlar için uygundur — senkron SideEffect’te bu imkansızdır.

SideEffect çok sık çalışıyorsa nasıl hata ayıklanır?

Android Studio Compose Modifier Debugger kullanın veya bileşen adı ve çağrı sıklığı ile günlük kaydı ekleyin. SideEffect beklenenden daha sık çalışıyorsa, üst bileşenin durumunun gereksiz yere değişip değişmediğini kontrol edin. Optimizasyon: kullanıcı arayüzünün kararlı kısımlarını unstable notlarıyla ayrı composable işlevlerine çıkararak yeniden oluşturma sayısını azaltın.

SideEffect DisposableEffect ile birleştirilebilir mi?

Evet, farklı amaçlar için aynı bileşende kullanılabilirler. DisposableEffect bir kaynağın kurulumu ve temizliğinden (bir kez) sorumluyken, SideEffect her yeniden oluşturmada mevcut durumun bu kaynakla senkronizasyonunu yönetir. Tipik bir örnek: DisposableEffect bir API aracılığıyla bir geri çağırma kaydeder ve SideEffect her değişiklikte bu geri çağırmadaki yakalanan verileri günceller.

Özet

  • SideEffect — Jetpack Compose’da her başarılı yeniden oluşturmadan sonra çalıştırılan senkron kod için yan etki API’si.
  • Senkronizasyon — ana kullanım durumu: Compose durumunu harici sistemlere (Google Maps, WebView, ViewPager, Analytics SDK) aktarmak.
  • Geri çağırmalar — SideEffect, mevcut durumu yakalayan geri çağırma işlevlerinin her kullanıcı arayüzü güncellemesinde güncel kalmasını sağlar.
  • Döngü yok — oluşturma aşamasından sonra çalışır, bu nedenle SideEffect içinde durum değiştirmek sonsuz yeniden oluşturmaya neden olmaz.
  • Sınırlamalar — anahtarları, asenkronizasyonu veya temizleme bloğunu desteklemez; bu görevler için LaunchedEffect veya DisposableEffect kullanın.
  • Performans — SideEffect içinde ağır hesaplamalardan kaçının, çünkü her yeniden oluşturmada çalışır (saniyede 60 kata kadar).
  • Hata ayıklama — Compose Debugger aracılığıyla çağrı sıklığını kontrol edin ve gereksiz yeniden oluşturmaları filtrelemek için remember ile optimize edin.

Anahtar teslim bir mobil uygulama geliştireceğiz

IT Sectr, 2017'den beri girişimler ve işletmeler için iOS ve Android uygulamaları oluşturmaktadır. Size danışmanlık yapacak ve en iyi çözümü önereceğiz.

Projeyi tartış

Ayrıca okuyun