SideEffect — یہ کیا ہے، Jetpack Compose میں حالت کی مطابقت پذیری

مصنف: IT Sectr اشاعت: 2026-06-30 مطالعے کا وقت: 9 منٹ

SideEffect Jetpack Compose میں ایک composable فنکشن ہے جو ہر کامیاب دوبارہ ترکیب (recomposition) پر منتقل کردہ کوڈ بلاک کو چلاتا ہے۔ LaunchedEffect اور DisposableEffect کے برعکس، SideEffect کلیدوں سے منسلک نہیں ہے اور اس میں صفائی کا بلاک نہیں ہے — یہ ہر رینڈرنگ کے بعد Compose حالت کو بیرونی نظاموں کے ساتھ صرف مطابقت پذیر کرتا ہے۔ یہ اسے کال بیک فنکشنز کو اپ ڈیٹ کرنے، ViewPager کے ساتھ مطابقت پذیری اور Analytics SDK کو ڈیٹا منتقل کرنے کے لیے مثالی بناتا ہے۔ Android Developers Documentation (2025) کے مطابق، SideEffect اس وقت چلتا ہے جب Compose کامیاب دوبارہ ترکیب کی تصدیق کرتا ہے، اور اگر دوبارہ ترکیب چھوڑ دی جائے تو نہیں چلتا۔

اہم نکات

  • SideEffect — ہر کامیاب دوبارہ ترکیب کے بعد چلنے والے کوڈ کے لیے سائیڈ ایفیکٹ API۔
  • مطابقت پذیری — Compose حالت کو بیرونی نظاموں میں منتقل کرتا ہے جو Compose کو سپورٹ نہیں کرتے۔
  • کلیدوں کے بغیر — LaunchedEffect کے برعکس، SideEffect دوبارہ شروع نہیں ہوتا بلکہ ہر دوبارہ ترکیب پر چلتا ہے۔
  • صفائی نہیں — SideEffect onDispose فراہم نہیں کرتا، یہ صرف یک طرفہ مطابقت پذیری کے لیے ڈیزائن کیا گیا ہے۔
  • مطابقت پذیر — بلاک کوروٹین کے بغیر، Compose کمپوزیشن فیز کے اندر مطابقت پذیر طریقے سے چلتا ہے۔

Jetpack Compose میں SideEffect کیا ہے

SideEffect Jetpack Compose میں سب سے آسان سائیڈ ایفیکٹ API ہے۔ یہ ایک composable جزو کی ہر کامیاب دوبارہ ترکیب پر ایک کوڈ بلاک چلاتا ہے۔ یہاں "کامیاب" لفظ کلیدی ہے: اگر Compose فیصلہ کرتا ہے کہ دوبارہ ترکیب ضروری نہیں ہے (مثال کے طور پر، تمام ان پٹ پیرامیٹرز میں تبدیلی نہیں آئی اور نتیجہ وہی ہوگا)، تو SideEffect نہیں چلتا۔ یہ یقینی بناتا ہے کہ مطابقت پذیری بلاک صرف اس وقت بلایا جائے جب یوزر انٹرفیس واقعی تبدیل ہوا ہو۔

SideEffect کا بنیادی استعمال Compose حالت کو ان اشیاء کے ساتھ مطابقت پذیر کرنا ہے جو Compose درخت کا حصہ نہیں ہیں۔ عام مثالوں میں شامل ہیں: Legacy View سسٹم میں کال بیک فنکشن کو اپ ڈیٹ کرنا، ViewPager کو موجودہ حالت منتقل کرنا، ڈسپلے کردہ ڈیٹا تبدیل ہونے پر Analytics SDK کو ایک واقعہ بھیجنا، اور میپنگ SDK کے ساتھ مطابقت پذیری کرنا جو بیرونی فارمیٹ میں اپ ڈیٹس کی توقع رکھتے ہیں۔

Android Developer Blog (2025) کے مطابق، SideEffect اکثر remember کے ساتھ استعمال ہوتا ہے: remember ایک شے (مثلاً ایک کال بیک) کو محفوظ رکھتا ہے، اور SideEffect جب بھی کوئی انحصار تبدیل ہوتا ہے اسے اپ ڈیٹ کرتا ہے۔ یہ پیٹرن خاص طور پر ان لائبریریوں کے لیے اہم ہے جو لسنر اشیاء قبول کرتی ہیں اور اپ ڈیٹ پر انہیں دوبارہ نہیں بناتیں — SideEffect کے بغیر، لسنر موجودہ حالت کا ایک پرانا حوالہ رکھے گا۔

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 کیسے کام کرتا ہے اور کمپوزیشن کے مراحل

SideEffect کو سمجھنے کے لیے، Jetpack Compose کے عملدرآمد کے مراحل کو سمجھنا ضروری ہے۔ Compose ہر فریم کے لیے تین مراحل سے گزرتا ہے: Composition (کیا دکھانا ہے)، Layout (کہاں دکھانا ہے)، Drawing (کیسے دکھانا ہے)۔ SideEffect Composition مرحلے کے آخر میں چلتا ہے — تمام composable فنکشنز چلنے کے بعد، لیکن Layout مرحلے سے پہلے۔ یہ یقینی بناتا ہے کہ SideEffect دوبارہ ترکیب کے بعد تمام متغیرات کی آخری حالت دیکھتا ہے۔

زندگی کے چکر میں یہ مقام ایک اہم فائدہ دیتا ہے: SideEffect لامحدود دوبارہ ترکیب کا سبب نہیں بن سکتا، چاہے اس کے اندر حالت تبدیل کی جائے۔ چونکہ یہ کمپوزیشن کے بعد چلتا ہے، SideEffect کے اندر کی گئی تبدیلیاں صرف اگلے فریم میں لاگو ہوں گی — یہ ایک composable فنکشن کے جسم کے اندر حالت کی تبدیلیوں کے عام چکروں کو روکتا ہے (جب کمپوزیشن کے اندر setState موجودہ کمپوزیشن ختم ہونے سے پہلے ایک نئی کمپوزیشن کو متحرک کرتا ہے)۔

ایک اور خصوصیت یہ ہے کہ SideEffect کلیدوں کے ذریعے بہتر نہیں کیا جاتا۔ یہ ہر دوبارہ ترکیب پر چلتا ہے چاہے کسی بھی مخصوص حالت میں تبدیلی آئی ہو۔ اگر آپ کو زیادہ درست کنٹرول کی ضرورت ہے (صرف اس وقت چلائیں جب کوئی مخصوص پیرامیٹر تبدیل ہو)، تو کلیدوں کے ساتھ LaunchedEffect استعمال کریں یا SideEffect کو remember کے ذریعے تبدیلی کی جانچ میں لپیٹ دیں۔

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 کے ساتھ کال بیک فنکشنز کو اپ ڈیٹ کرنا

SideEffect کے لیے سب سے عام عملی منظرنامہ موجودہ حالت کو کیپچر کرنے والے کال بیک فنکشنز کو اپ ڈیٹ کرنا ہے۔ Jetpack Compose میں اسے "کال بیک لائف سائیکل مینجمنٹ" کہا جاتا ہے۔ مسئلہ یہ ہے کہ Kotlin میں lambda اظہارات متغیرات کو حوالہ سے کیپچر کرتے ہیں، اور اگر ایک کال بیک ایک قدر کے ساتھ بنایا گیا اور بعد میں متغیر تبدیل ہوگیا — تو کال بیک پرانی قدر استعمال کرتا رہتا ہے۔

ایک مثال پر غور کریں: Android کے لیے Google Maps SDK setOnCameraMoveListener() کے ذریعے ایک OnCameraMoveListener شے قبول کرتا ہے۔ اگر آپ ایک lambda منتقل کرتے ہیں جو isTrackingEnabled کو کیپچر کرتا ہے، تو جب isTrackingEnabled تبدیل ہوگا تو lambda اپ ڈیٹ نہیں ہوگا — Maps SDK پرانے ڈیٹا کے ساتھ پرانے کال بیک کو کال کرتا رہے گا۔ SideEffect اس مسئلے کو حل کرتا ہے: یہ ہر دوبارہ ترکیب پر لسنر کو دوبارہ سیٹ کرتا ہے، اس بات کو یقینی بناتا ہے کہ SDK ہمیشہ تازہ ترین حالت کے ساتھ موجودہ lambda استعمال کرے۔

Android کے لیے Maps SDK دستاویز (2025) کے مطابق، Google Maps کو Jetpack Compose کے ساتھ مربوط کرتے وقت بالکل اسی پیٹرن کی سفارش کرتا ہے۔ اسی طرح کا طریقہ WebView، VideoView، TextureView اور کسی بھی دوسرے View پر مبنی اجزاء کے لیے استعمال ہوتا ہے جو set طریقوں کے ذریعے کال بیک قبول کرتے ہیں۔ SideEffect یقینی بناتا ہے کہ ہر حالت کی تبدیلی کے ساتھ کال بیک اپ ڈیٹ رہیں۔

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 کے ساتھ مطابقت پذیری

SideEffect کے لیے ایک اور اہم منظرنامہ یوزر انٹرفیس کی حالت تبدیل ہونے پر تجزیہ کے نظاموں کو واقعات بھیجنا ہے۔ مثال کے طور پر، جب کوئی صارف Compose اسکرین کے اندر TabLayout میں ٹیب تبدیل کرتا ہے، SideEffect موجودہ منتخب ٹیب کی حالت Firebase Analytics یا AppsFlyer کو منتقل کر سکتا ہے۔ جب بھی منتخب ٹیب تبدیل ہوتا ہے (اور دوبارہ ترکیب ہوتی ہے)، SideEffect متعلقہ واقعہ بھیجتا ہے۔

واقعات کو براہ راست onClick یا onTabSelected میں بھیجنے سے فرق یہ ہے کہ SideEffect کسی بھی ذریعہ سے حالت کی تبدیلیوں پر متحرک ہوتا ہے — نہ صرف صارف کے اعمال، بلکہ پروگرامی تبدیلیاں، اسکرین گھومنے کے بعد حالت کی بحالی یا ڈیپ لنکس بھی۔ یہ SideEffect کو تبدیلی کے ذریعہ سے آزاد ایک عالمگیر مطابقت پذیری طریقہ کار بناتا ہے۔

Firebase Best Practices (Google, 2025) کے مطابق، SideEffect کے ذریعے تجزیہ کے واقعات بھیجنا صارف کے سفر کی ایک زیادہ مکمل تصویر فراہم کرتا ہے، کیونکہ یہ حالت کی تمام تبدیلیوں کو کیپچر کرتا ہے، بشمول وہ جو براہ راست صارف کے عمل کے بغیر ہوتی ہیں۔ تاہم، اسے زیادہ نہ کرنا ضروری ہے: ہر تجزیہ کا واقعہ ایک نیٹ ورک کی درخواست ہے، لہذا بار بار تبدیل ہونے والی حالتوں (اسکرول پوزیشن، انگلی کے نقاط) کے لیے SideEffect موزوں نہیں ہے — ڈیباؤنس استعمال کریں یا صرف اہم تبدیلیوں پر واقعات بھیجیں۔

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 بمقابلہ LaunchedEffect: کب کیا استعمال کریں

SideEffect اور LaunchedEffect کے درمیان انتخاب دو عوامل پر منحصر ہے: کیا غیر مطابقت پذیر عملدرآمد ضروری ہے اور کیا کلید پر مبنی کنٹرول ضروری ہے۔ SideEffect مطابقت پذیر ہے اور ہر دوبارہ ترکیب پر چلتا ہے۔ LaunchedEffect غیر مطابقت پذیر (کوروٹین) ہے اور صرف اس وقت چلتا ہے جب کوئی کلید تبدیل ہوتی ہے، ہر دوبارہ ترکیب پر نہیں۔

خصوصیتSideEffectLaunchedEffect
عملدرآمدہر دوبارہ ترکیب پرکلید کی تبدیلی پر
غیر مطابقت پذیریمطابقت پذیرکوروٹین
کلیدیںنہیںہاں (vararg)
صفائینہیںخودکار کوروٹین منسوخی
عام استعمالکال بیک، تجزیہ، منظر مطابقت پذیریلوڈنگ، Flow سبسکرپشن، ٹائمر

عملی طور پر، سائیڈ ایفیکٹ کے 70% استعمالات LaunchedEffect (غیر مطابقت پذیر کارروائیاں، ڈیٹا لوڈنگ)، 20% DisposableEffect (صفائی کے ساتھ وسائل) اور صرف 10% SideEffect (کال بیک مطابقت پذیری) کے ذریعے پورے ہوتے ہیں۔ SideEffect کاموں کی ایک محدود رینج کے لیے ایک خصوصی آلہ ہے، لیکن ان کاموں میں یہ ناگزیر ہے۔

SideEffect کے ساتھ عام غلطیاں

بنیادی غلطی SideEffect کے اندر Compose حالت کو تبدیل کرنا ہے۔ اگرچہ SideEffect براہ راست لامحدود لوپ کا سبب نہیں بنتا (کیونکہ یہ کمپوزیشن مرحلے کے بعد چلتا ہے)، یہ ضرورت سے زیادہ دوبارہ ترکیب کو متحرک کر سکتا ہے۔ اگر SideEffect کے اندر حالت تبدیل کی جائے (mutableStateOf)، تو یہ اگلے فریم میں ایک نئی دوبارہ ترکیب کو متحرک کرتا ہے، جو پھر SideEffect چلاتا ہے — اور یہ استحکام تک جاری رہتا ہے۔ یہ لامحدود لوپ نہیں ہے، لیکن فریم ورک کے لیے غیر ضروری کام ہے۔

دوسری غلطی SideEffect کے اندر بھاری حسابات کرنا ہے۔ چونکہ SideEffect ہر دوبارہ ترکیب پر بلایا جاتا ہے، اور دوبارہ ترکیبیں سیکنڈ میں درجنوں بار ہو سکتی ہیں (اینیمیشن، اسکرولنگ کے دوران)، SideEffect کے اندر کوئی بھی بھاری کوڈ فریم ڈراپ کا سبب بنے گا۔ بھاری کارروائیوں کو کمپوزیشن سے باہر منتقل کریں — کوروٹین (LaunchedEffect) میں یا derivedStateOf / remember کے ذریعے حساب کریں۔

تیسری غلطی SideEffect کو غیر مطابقت پذیر کوڈ کے لیے استعمال کرنے کی کوشش کرنا ہے۔ SideEffect ایک suspend فنکشن نہیں ہے، لہذا delay()، await()، collect() اور دیگر کوروٹین کارروائیاں اس کے اندر مرتب نہیں ہوں گی۔ اگر آپ کو دوبارہ ترکیب کے بعد ایک غیر مطابقت پذیر کارروائی کرنے کی ضرورت ہے، تو LaunchedEffect کے ساتھ snapshotFlow { ... } استعمال کریں، یا rememberCoroutineScope کے ذریعے کوروٹین شروع کریں۔

اکثر پوچھے گئے سوالات

کیا SideEffect پہلی کمپوزیشن پر چلتا ہے؟

ہاں، SideEffect ہر کامیاب کمپوزیشن پر چلتا ہے، پہلی بھی شامل ہے — جب جزو پہلی بار اسکرین پر ظاہر ہوتا ہے۔ یہ LaunchedEffect(Unit) سے مختلف ہے، جو پہلی کمپوزیشن پر ایک بار چلتا ہے لیکن بعد کی دوبارہ ترکیبوں پر نہیں چلتا (اگر کلید تبدیل نہیں ہوئی)۔

کیا SideEffect لامحدود لوپ کا سبب بن سکتا ہے؟

نہیں، SideEffect کمپوزیشن مرحلے کے بعد چلتا ہے — اس کے اندر کی گئی تبدیلیاں صرف اگلے فریم میں لاگو ہوں گی، جو لوپ کو روکتی ہے۔ تاہم، SideEffect کے اندر بار بار حالت تبدیل کرنا دوبارہ ترکیب کا ایک سلسلہ شروع کر سکتا ہے، جس سے کارکردگی کم ہو سکتی ہے۔ SideEffect کے اندر حالت صرف اس وقت تبدیل کریں جب واقعی ضروری ہو۔

SideEffect اور snapshotFlow میں کیا فرق ہے؟

SideEffect ہر دوبارہ ترکیب پر مطابقت پذیر طریقے سے چلتا ہے۔ snapshotFlow Compose حالت سے ایک Flow بناتا ہے اور ردعمل کی تبدیلی کی کارروائی کے لیے LaunchedEffect میں collectLatest کے ساتھ استعمال کیا جا سکتا ہے۔ snapshotFlow ان صورتوں کے لیے موزوں ہے جہاں آپ کو debounce، filter یا distinctUntilChanged کے ساتھ تبدیلیوں کا جواب دینے کی ضرورت ہے — جو مطابقت پذیر SideEffect میں ناممکن ہے۔

اگر SideEffect بہت بار چلتا ہے تو ڈیبگ کیسے کریں؟

Android Studio Compose Modifier Debugger استعمال کریں یا جزو کے نام اور کال فریکوئنسی کے ساتھ لاگنگ شامل کریں۔ اگر SideEffect توقع سے زیادہ بار چلتا ہے تو چیک کریں کہ آیا والد جزو کی حالت غیر ضروری طور پر تبدیل ہو رہی ہے۔ اصلاح: یوزر انٹرفیس کے مستحکم حصوں کو unstable تشریحات کے ساتھ علیحدہ composable فنکشنز میں نکالیں تاکہ دوبارہ ترکیب کی تعداد کم ہو۔

کیا SideEffect کو DisposableEffect کے ساتھ ملایا جا سکتا ہے؟

ہاں، انہیں مختلف مقاصد کے لیے ایک ہی جزو میں استعمال کیا جا سکتا ہے۔ DisposableEffect ایک وسیلہ کے سیٹ اپ اور صفائی (ایک بار) کے لیے ذمہ دار ہے، جبکہ SideEffect ہر دوبارہ ترکیب پر اس وسیلہ کے ساتھ موجودہ حالت کی مطابقت پذیری کا انتظام کرتا ہے۔ ایک عام مثال: DisposableEffect ایک API کے ذریعے کال بیک رجسٹر کرتا ہے، اور SideEffect ہر تبدیلی پر اس کال بیک میں کیپچر کردہ ڈیٹا کو اپ ڈیٹ کرتا ہے۔

خلاصہ

  • SideEffect — Jetpack Compose میں ہر کامیاب دوبارہ ترکیب کے بعد چلنے والے مطابقت پذیر کوڈ کے لیے سائیڈ ایفیکٹ API۔
  • مطابقت پذیری — بنیادی استعمال: Compose حالت کو بیرونی نظاموں (Google Maps، WebView، ViewPager، Analytics SDK) میں منتقل کرنا۔
  • کال بیک — SideEffect یقینی بناتا ہے کہ موجودہ حالت کو کیپچر کرنے والے کال بیک فنکشنز ہر UI اپ ڈیٹ کے ساتھ تازہ ترین رہیں۔
  • کوئی لوپ نہیں — کمپوزیشن مرحلے کے بعد چلتا ہے، لہذا SideEffect کے اندر حالت تبدیل کرنا لامحدود دوبارہ ترکیب کا سبب نہیں بنتا۔
  • محدودیتیں — کلیدوں، غیر مطابقت پذیری یا صفائی کے بلاک کو سپورٹ نہیں کرتا؛ ان کاموں کے لیے LaunchedEffect یا DisposableEffect استعمال کریں۔
  • کارکردگی — SideEffect کے اندر بھاری حسابات سے بچیں، کیونکہ یہ ہر دوبارہ ترکیب پر چلتا ہے (فی سیکنڈ 60 بار تک)۔
  • ڈیبگنگ — Compose Debugger کے ذریعے کال فریکوئنسی کو کنٹرول کریں اور غیر ضروری دوبارہ ترکیب کو فلٹر کرنے کے لیے remember کے ساتھ بہتر بنائیں۔

ہم ایک موبائل ایپلیکیشن ٹرنکی تیار کریں گے

IT Sectr 2017 سے اسٹارٹ اپس اور کاروبار کے لیے iOS اور Android ایپلیکیشنز بناتا ہے۔ ہم آپ کو مشورہ دیں گے اور بہترین حل تجویز کریں گے۔

پروجیکٹ پر بحث کریں

مزید پڑھیں