SideEffect — nədir, Jetpack Compose-da vəziyyət sinxronizasiyası

Müəllif: IT Sectr Dərc olunub: 2026-06-30 Oxuma vaxtı: 9 dəq

SideEffect — Jetpack Compose-da hər uğurlu rekompozisiyada verilmiş kod blokunu icra edən composable funksiyadır. LaunchedEffect və DisposableEffect-dən fərqli olaraq, SideEffect açarlara bağlı deyil və təmizləmə bloku yoxdur — o, sadəcə hər renderdən sonra Compose vəziyyətini xarici sistemlərlə sinxronlaşdırır. Bu onu callback funksiyalarının yenilənməsi, ViewPager ilə sinxronizasiya və Analytics SDK-ya məlumat ötürülməsi üçün ideal edir. Android Developers Documentation (2025)-a görə, SideEffect Compose uğurlu rekompozisiyanı təsdiqlədikdən sonra ciddi şəkildə icra olunur və rekompozisiya buraxıldıqda icra olunmur.

Əsas məqamlar

  • SideEffect — hər uğurlu rekompozisiyadan sonra icra olunan kod üçün side-effect API.
  • Sinxronizasiya — Compose-u dəstəkləməyən xarici sistemlərə Compose vəziyyətini ötürür.
  • Açarsız — LaunchedEffect-dən fərqli olaraq, SideEffect yenidən başlamır, hər rekompozisiyada icra olunur.
  • Təmizləmə yoxdur — SideEffect onDispose təmin etmir, yalnız birtərəfli sinxronizasiya üçün nəzərdə tutulub.
  • Sinxronluq — blok kompozisiya mərhələsində sinxron şəkildə, korutinsiz icra olunur.

Jetpack Compose-da SideEffect nədir

SideEffect — Jetpack Compose-da ən sadə side-effect API-dir. Composable komponentinin hər uğurlu rekompozisiyasında kod blokunu icra edir. Burada „uğurlu“ sözü əsasdır: əgər Compose rekompozisiyanın tələb olunmadığını qərara alıbsa (məsələn, bütün giriş parametrləri dəyişməyib və nəticə eyni olacaq), SideEffect icra olunmur. Bu, sinxronizasiya blokunun yalnız UI həqiqətən dəyişdikdə çağrılmasını təmin edir.

SideEffect-in əsas istifadə ssenarisi — Compose vəziyyətinin Compose ağacının hissəsi olmayan obyektlərlə sinxronizasiyasıdır. Tipik nümunələr: Legacy View sistemində callback funksiyasının yenilənməsi, cari vəziyyətin ViewPager-ə ötürülməsi, göstərilən məlumatlar dəyişdikdə Analytics SDK-ya hadisə göndərilməsi, xarici formatda yeniləmə gözləyən xəritəçəkmə SDK-ları ilə sinxronizasiya.

Android Developer Blog (2025)-a görə, SideEffect tez-tez remember ilə birlikdə istifadə olunur: remember obyekti (məsələn, callback) saxlayır, SideEffect isə onu hər asılılıq dəyişikliyində yeniləyir. Bu nümunə listener obyektlərini qəbul edən və yeniləmə zamanı onları yenidən yaratmayan kitabxanalar üçün xüsusilə vacibdir — SideEffect olmadan listener cari vəziyyətə köhnə istinadı saxlayardı.

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 necə işləyir və kompozisiya mərhələləri

SideEffect-i başa düşmək üçün Jetpack Compose-un icra mərhələlərini bilmək lazımdır. Compose hər kadr üçün üç mərhələdən keçir: Composition (nə göstəriləcək), Layout (harada göstəriləcək), Drawing (necə göstəriləcək). SideEffect Composition mərhələsinin sonunda — bütün composable funksiyalar işlədikdən sonra, lakin Layout mərhələsindən əvvəl icra olunur. Bu, SideEffect-in rekompozisiyadan sonra bütün dəyişənlərin yekun vəziyyətini görməsini təmin edir.

Həyat dövründəki bu yerləşmə mühüm üstünlük verir: SideEffect içərisində vəziyyət dəyişsə belə, sonsuz rekompozisiyaya səbəb ola bilməz. Kompozisiyadan sonra icra olunduğu üçün SideEffect daxilində edilən dəyişikliklər yalnız növbəti kadrda nəzərə alınacaq — bu, composable funksiya gövdəsindəki dəyişikliklərə xas olan dövrlərin qarşısını alır (kompozisiya daxilində setState cari kompozisiya bitməmiş yenisini tetiklədikdə).

Digər bir xüsusiyyət — SideEffect açarlarla optimallaşdırılmır. Hansı vəziyyətin dəyişməsindən asılı olmayaraq hər rekompozisiyada icra olunur. Əgər daha dəqiq nəzarət tələb olunursa (yalnız müəyyən parametr dəyişdikdə icra etmək), açarlarla LaunchedEffect istifadə edin və ya SideEffect-i remember vasitəsilə dəyişiklik yoxlamasına sarın.

kotlin
// remember ilə optimallaşdırılmış SideEffect
var currentZoom by remember { mutableIntStateOf(zoomLevel) }

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

// Bu yoxlama olmadan SideEffect animateToZoom-u çağıracaqdı
// hər rekompozisiyada, hətta zoomLevel dəyişməsə belə

SideEffect vasitəsilə callback funksiyalarının yenilənməsi

SideEffect üçün ən çox yayılmış praktik ssenari — cari vəziyyəti bağlayan callback funksiyalarının yenilənməsidir. Jetpack Compose-da buna „callback lifecycle management“ deyilir. Problem ondadır ki, Kotlin-də lambda ifadələri dəyişənləri istinadla tutur və əgər callback dəyişənin bir qiyməti ilə yaradılıbsa, sonra dəyişən dəyişibsə — callback köhnə qiyməti istifadə etməyə davam edir.

Bir nümunəyə baxaq: Android üçün Google Maps SDK OnCameraMoveListener obyektini setOnCameraMoveListener() vasitəsilə qəbul edir. isTrackingEnabled-i tutan bir lambda ötürsəniz, isTrackingEnabled dəyişdikdə lambda yenilənməyəcək — Maps SDK köhnə məlumatlarla köhnə callback-i çağırmağa davam edəcək. SideEffect bu problemi həll edir: hər rekompozisiyada listener-i yenidən qurur, SDK-nın həmişə cari vəziyyətlə aktual lambdadan istifadə etməsini təmin edir.

Android üçün Maps SDK Sənədləşməsi (2025)-nə görə, Google Maps-i Jetpack Compose ilə inteqrasiya edərkən məhz bu nümunəni tövsiyə edir. Bənzər yanaşma WebView, VideoView, TextureView və set-metodlar vasitəsilə callback qəbul edən digər View-based komponentlər üçün istifadə olunur. SideEffect hər vəziyyət dəyişikliyində callback-lərin aktuallığını təmin edir.

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 ilə sinxronizasiya

SideEffect-in digər mühüm ssenarisi — UI vəziyyəti dəyişdikdə analitik sistemlərə hadisələr göndərməkdir. Məsələn, istifadəçi Compose ekranı daxilində TabLayout-da vərəqləri dəyişdikdə, SideEffect seçilmiş vərəqin cari vəziyyətini Firebase Analytics və ya AppsFlyer-ə ötürə bilər. Seçilmiş vərəq hər dəfə dəyişdikdə (və rekompozisiya baş verdikdə), SideEffect müvafiq hadisəni göndərir.

Hadisələri birbaşa onClick və ya onTabSelected daxilində göndərməkdən fərq ondadır ki, SideEffect istənilən yolla — təkcə istifadəçi hərəkəti ilə deyil, həm də proqram dəyişikliyi, ekranın fırlanmasından sonra vəziyyətin bərpası və ya Deep Link vasitəsilə yaranan vəziyyət dəyişikliyinə reaksiya verir. Bu, SideEffect-i dəyişiklik mənbəyindən asılı olmayan universal sinxronizasiya mexanizminə çevirir.

Firebase Best Practices (Google, 2025)-a görə, analitik hadisələrin SideEffect vasitəsilə göndərilməsi istifadəçi yolunun daha dolğun mənzərəsini verir, çünki birbaşa istifadəçi hərəkəti olmadan baş verən dəyişikliklər də daxil olmaqla bütün vəziyyət dəyişikliklərini qeydə alır. Bununla belə, həddi aşmamaq vacibdir: Analytics-də hər hadisə şəbəkə sorğusudur, ona görə də tez-tez dəyişən vəziyyətlər (sürüşdürmə mövqeyi, barmaq koordinatları) üçün SideEffect uyğun deyil — debounce istifadə edin və ya hadisələri yalnız əhəmiyyətli dəyişikliklərdə göndərin.

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)
    }
    
    // TabRow və seçilmiş vərəq ilə UI
}

SideEffect vs LaunchedEffect: nə vaxt hansını istifadə etməli

SideEffectLaunchedEffect arasında seçim iki amildən asılıdır: asinxronluq lazımdırmı və açarlarla idarəetmə lazımdırmı. SideEffect sinxrondur və hər rekompozisiyada icra olunur. LaunchedEffect asinxrondur (korutin) və yalnız açar dəyişdikdə icra olunur, hər rekompozisiyada deyil.

Əgər hər UI dəyişikliyində hərəkət etmək lazımdırsa — SideEffect istifadə edin. Əgər hərəkəti bir dəfə ekran görünəndə və ya müəyyən parametr dəyişdikdə yerinə yetirmək lazımdırsa — açarlarla LaunchedEffect istifadə edin. Asinxron əməliyyat (məlumat yükləmə, gecikmə, Flow ilə iş) tələb olunarsa — yalnız LaunchedEffect, çünki SideEffect suspend funksiyalarını dəstəkləmir.

XüsusiyyətSideEffectLaunchedEffect
İcraHər rekompozisiyadaAçarlar dəyişdikdə
AsinxronluqSinxronKorutin
AçarlarYoxVar (vararg)
TəmizləməYoxKorutinin avtomatik ləğvi
Tipik tətbiqCallback-lər, Analytics, View sinxronizasiyasıYükləmə, Flow abunəliyi, taymerlər

Praktikada side effects istifadəsinin 70%-ni LaunchedEffect (asinxron əməliyyatlar, məlumat yükləmə), 20%-ni DisposableEffect (təmizləmə ilə resurslar) və yalnız 10%-ni SideEffect (callback funksiyalarının sinxronizasiyası) təşkil edir. SideEffect dar bir sıra tapşırıqlar üçün ixtisaslaşmış alətdir, lakin bu tapşırıqlarda əvəzolunmazdır.

SideEffect ilə tipik səhvlər

Əsas səhv — SideEffect daxilində Compose vəziyyətinin dəyişdirilməsi. SideEffect birbaşa sonsuz dövrəyə səbəb olmasa da (kompozisiya mərhələsindən sonra icra olunduğu üçün), həddindən artıq rekompozisiyalara səbəb ola bilər. SideEffect daxilində vəziyyət (mutableStateOf) dəyişdirilərsə, bu növbəti kadrda yeni rekompozisiyanı tetikləyər, o da yenidən SideEffect-i icra edəcək — və bu sabitləşməyə qədər davam edəcək. Bu sonsuz dövrə deyil, lakin framework üçün əlavə işdir.

İkinci səhv — SideEffect daxilində ağır hesablamaların aparılması. SideEffect hər rekompozisiyada çağrıldığından, rekompozisiyalar isə saniyədə dəfələrlə (animasiyalar, sürüşdürmə zamanı) baş verə bildiyindən, SideEffect daxilindəki hər ağır kod kadr itkisinə səbəb olacaq. Ağır əməliyyatları kompozisiyadan kənara — korutinə (LaunchedEffect) çıxarın və ya derivedStateOf / remember vasitəsilə hesablayın.

Üçüncü səhv — SideEffect-i asinxron kod üçün istifadə etmək cəhdi. SideEffect suspend funksiyası deyil, ona görə də onun daxilində delay(), await(), collect() və digər korutin əməliyyatları kompilyasiya olunmayacaq. Rekompozisiyadan sonra asinxron hərəkət yerinə yetirmək lazımdırsa, snapshotFlow { ... } kombinasiyasını LaunchedEffect ilə istifadə edin və ya rememberCoroutineScope vasitəsilə korutin işə salın.

Tez-tez verilən suallar

SideEffect ilk kompozisiyada icra olunurmu?

Bəli, SideEffect hər uğurlu kompozisiyada, o cümlədən birincidə — komponent ekranda yenicə görünəndə icra olunur. Bu, onu LaunchedEffect(Unit)-dən fərqləndirir, o da ilk kompozisiyada bir dəfə icra olunur, lakin sonrakı rekompozisiyalarda icra olunmur (əgər açar dəyişməyibsə).

SideEffect sonsuz dövrəyə səbəb ola bilərmi?

Xeyr, SideEffect kompozisiya mərhələsindən sonra icra olunur — onun daxilində edilən dəyişikliklər yalnız növbəti kadrda tətbiq olunacaq, bu da dövrələrin qarşısını alır. Bununla belə, SideEffect daxilində vəziyyətin tez-tez dəyişdirilməsi rekompozisiyaların selinə səbəb olaraq performansı aşağı sala bilər. Vəziyyəti SideEffect daxilində yalnız real zərurət olduqda dəyişdirin.

SideEffect və snapshotFlow arasında nə fərq var?

SideEffect hər rekompozisiyada sinxron icra olunur. snapshotFlow Compose vəziyyətindən Flow yaradır və LaunchedEffect-də collectLatest ilə dəyişikliklərin reaktiv emalı üçün istifadə edilə bilər. snapshotFlow debounce, filter və ya distinctUntilChanged ilə dəyişikliklərə reaksiya vermək lazım olan hallar üçün uyğundur — bu sinxron SideEffect-də mümkün deyil.

SideEffect çox tez-tez icra olunarsa, onu necə debug etməli?

Android Studio Compose Modifier Debugger istifadə edin və ya komponent adı və çağrılma tezliyi ilə loglama əlavə edin. SideEffect gözləniləndən daha tez-tez icra olunursa, valideyn komponentinin vəziyyətinin boş yerə dəyişmədiyini yoxlayın. Optimallaşdırma: UI-nin sabit hissələrini ayrıca composable funksiyalara unstable annotasiyaları ilə çıxarın ki, rekompozisiyaların sayı azalsın.

SideEffect-i DisposableEffect ilə birləşdirmək olarmı?

Bəli, onlar bir komponentdə müxtəlif məqsədlər üçün istifadə edilə bilər. DisposableEffect resursun qurulması və təmizlənməsi (bir dəfə) üçün cavabdehdir, SideEffect isə cari vəziyyətin bu resursla hər rekompozisiyada sinxronizasiyası üçün. Tipik nümunə: DisposableEffect API vasitəsilə callback-i qeydiyyatdan keçirir, SideEffect isə hər dəyişiklikdə bu callback-də bağlanan məlumatları yeniləyir.

Nəticə

  • SideEffect — Jetpack Compose-da hər uğurlu rekompozisiyadan sonra icra olunan sinxron kod üçün side-effect API.
  • Sinxronizasiya — əsas ssenari: Compose vəziyyətinin xarici sistemlərə (Google Maps, WebView, ViewPager, Analytics SDK) ötürülməsi.
  • Callback-lər — SideEffect hər UI yeniləməsində cari vəziyyəti bağlayan callback funksiyalarının aktuallığını təmin edir.
  • Dövrəsiz — kompozisiya mərhələsindən sonra icra olunur, ona görə də SideEffect daxilində vəziyyətin dəyişdirilməsi sonsuz rekompozisiyaya səbəb olmur.
  • Məhdudiyyətlər — açarları, asinxronluğu və təmizləmə blokunu dəstəkləmir; bu tapşırıqlar üçün LaunchedEffect və ya DisposableEffect istifadə edin.
  • Performans — SideEffect daxilində ağır hesablamalardan qaçın, çünki hər rekompozisiyada (saniyədə 60 dəfəyə qədər) icra olunur.
  • Debug — Compose Debugger vasitəsilə çağrılma tezliyinə nəzarət edin və lazımsız rekompozisiyaları süzmək üçün remember ilə optimallaşdırın.

Açar təslim mobil tətbiq hazırlayacağıq

IT Sectr 2017-ci ildən startaplar və bizneslər üçün iOS və Android tətbiqləri yaradır. Sizə məsləhət verəcəyik və ən yaxşı həlli təklif edəcəyik.

Layihəni müzakirə et

Həm də oxuyun