DisposableEffect — Jetpack Compose میں وسائل کی آزادی

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

DisposableEffect Jetpack Compose میں ایک composable فنکشن ہے جو ان کارروائیوں کے لیے ڈیزائن کیا گیا ہے جنہیں واضح آغاز اور اس کے بعد وسائل کی صفائی کی ضرورت ہوتی ہے۔ دیگر side-effect APIs کے برخلاف، DisposableEffect onDispose بلاک فراہم کرتا ہے جو گارنٹی سے اس وقت چلتا ہے جب کمپونینٹ کمپوزیشن چھوڑتا ہے یا کنجی بدلتی ہے۔ یہ اسے مقامی سبسکرائیپشنز، سینسر سننے والوں اور ہارڈویئر وسائل کے ساتھ کام کرنے کے لیے ناگزیر بناتا ہے۔ Android Developers Documentation (2025) کے مطابق، DisposableEffect کو ان سب مناظروں میں استعمال کرنے کی سفارش کی جاتی ہے جہاں setup/teardown جوڑے کی ضرورت ہو، Activity لائف سائکل میں onStart/onStop کے مشابہ۔

اہم نکات

  • DisposableEffect — سیٹ اپ اور گارنٹی شدہ وسائل کی صفائی کے لیے side-effect API۔
  • onDispose — لازمی بلاک جو کمپوزیشن چھوڑتے وقت یا کنجی بدلتے وقت چلتا ہے۔
  • سنکرونس — LaunchedEffect کے برخلاف، DisposableEffect کوروٹینز کے بغیر سنکرونس کام کرتا ہے۔
  • صفائی — معمولی مناظر: LiveData سے سبسکرائیپشن منسوخکرنا، سوکٹ بند کرنا، BroadcastReceiver کی رجسٹریشن منسوخ کرنا۔
  • کنجیاں — جب کنجی بدلتی ہے، پرانی قیمت کے لیے onDispose چلتا ہے اور نئی قیمت کے ساتھ دوبارہ آغاز ہوتا ہے۔

Jetpack Compose میں DisposableEffect کیا ہے

DisposableEffect Jetpack Compose میں وسائل کے انتظام کے لیے ایک کلیڈی ٹول ہے۔ اسکی اہم خصوصیت composable کمپونینٹ کے لائف سائکل کے ختم ہونے پر onDispose بلاک کا گارنٹی شدہ طلب ہے۔ یہ رویہ Android ڈیولپمنٹ کے لیے بہت اہم ہے، جہاں سسٹم سروسز کی بند نہ ہونے والی رکابیتیاں میموری لیکس اور ایپلیکیشن کی کریش کا سبب بن سکتی ہیں۔

LaunchedEffect کے برخلاف جو ایک کوروٹین کے اسنکرونس سی اق میں کام کرتا ہے، DisposableEffect سنکرونس طور پر چلتا ہے۔ اسکا مطلب ہے کہ آپ اس کے اندر suspend فنکشنز نہیں بولا سکت۔۔ سنکرونس ایگزیکیوشن پیش قیاسیتا کی ضمانت دیتا ہے: آپ یقین ہو سکتے ہیں کہ آغاز کا کوڈ پہلی رنڈرنگ سے پہلے اور صفائی کا کوڈ کمپونینٹ کے میموری سے ہٹانے سے پہلے چلتا ہے۔

Jetpack Compose دستاویز (2025) کے مطابق، DisposableEffect کو چار بنیادی مناظروں میں استعمال کرنا چاہیے: (1) سسٹم سروسز (سینسرز، LocationManager) کی رکابیتی، (2) BroadcastReceiver کی رجسٹریشن، (3) کوروٹینز کی حمایت نہ کرنے والی callback-based لائبریریز کے ساتھ کام، (4) AndroidView کے ذریعے Compose کمپونینٹس کو لگیسی View سسٹمز سے منسلک کرنا۔

kotlin
class SensorManager(private val context: Context) {
    fun startListening(callback: (Float) -> Unit) { /* register */ }
    fun stopListening() { /* cancel */ }
}

@Composable
fun SensorDisplay() {
    val sensorManager = remember { SensorManager(context) }
    var value by remember { mutableStateOf(0f) }
    
    DisposableEffect(Unit) {
        sensorManager.startListening { value = it }
        onDispose { sensorManager.stopListening() }
    }
    
    Text("سینسر: $value")
}

DisposableEffect onDispose کے ساتھ کیسے کام کرتا ہے

DisposableEffect کی اندرونی میکانزم کمپوزیشن لائف سائکل کے مراحل پر مبنی ہے۔ جب ایک composable کمپونینٹ کمپوزیشن میں داخل ہوتا ہے، DisposableEffect گزرے گئے کوڈ بلاک کو چلاتا ہے۔ یہ بلاک onDispose lambda پر مشتمل DisposableEffectResult آبجیکٹ واپس کرتا ہے۔ کمپوزیشن اس نتیجے کو محفوظ کرتی ہے اور جب کمپونینٹ کمپوزیشن چھوڑتا ہے onDispose کو طلب کرتی ہے — وجہ کئی بھی ہو (نیویگیشن، والد کی حالت میں تبدیلی، LazyColumn سے ہٹانا)۔

DisposableEffect میں کنجی کا میکانزم LaunchedEffect کے مشابہ کام کرتا ہے: جب کئی کنجی بدلتی ہے، پہلے onDispose پرانی حالت کے لیے چلتا ہے، پھر آغاز کا بلاک نئی کنجیوں کے ساتھ دوبارہ چلتا ہے۔ یہ آپکو اس کے پیرامیٹرز بدلنے پر وسیلے کو دوبارہ ترتیب دینے کی اجازت دیتا ہے۔ مثال کے طور پر، اگر کنجی ایک سوکٹ URL ہے، تو اس کے بدلنے پر پرانا سوکٹ بند ہوتا ہے اور ایک نءی کھل جاتی ہے۔

اہم: onDispose بلاک DisposableEffect کا ایک لازمی عنصر ہے۔ اگر آپ بلاک کے اندر onDispose نہیں بلاتے، تو کوڈ کامپائل نہیں ہوگا۔ کامپائلر کا یہ تقاضہ اس بات کی ضمانت دیتا ہے کہ ڈیولپر وسیلے کی صفائی فراہم کرنا نہیں بھولتا، جو دستی رکابیتی انتظام میں غلطیوں کی ایک عام وجہ ہے۔

kotlin
// ایک کنجی کے ساتھ صحیح استعمال
DisposableEffect(sensorType) {
    val sensor = sensorManager.getDefaultSensor(sensorType)
    sensorManager.registerListener(listener, sensor, SensorManager.SENSOR_DELAY_NORMAL)
    
    onDispose {
        sensorManager.unregisterListener(listener)
    }
}

// ایک DisposableEffect میں متعدد وسائل
DisposableEffect(Unit) {
    context.registerReceiver(receiver, intentFilter)
    lifecycle.addObserver(observer)
    
    onDispose {
        context.unregisterReceiver(receiver)
        lifecycle.removeObserver(observer)
    }
}

DisposableEffect بنام میموری لیک

Android ایپلیکیشنز میں میموری لیک اکسر ان رجسٹر شدہ سننے والوں اور رکابیتیوں کے نتیجے میں ہوتی ہیں جو سکرین بند ہونے کے بعد بھی Activity یا Context کا حوالہ رکھتی رہتی ہیں۔ DisposableEffect اس مسئلے کو فریم ورک کی سطح پر حل کرتا ہے: اگر کوئی ڈیولپر ایک سننے والے کی رجسٹریشن کے لیے DisposableEffect استعمال کرتا ہے، onDispose کسی بھی کمپونینٹ اختتام کے منظر میں رکابیتی منسوخ کرنے کی ضمانت دیگا۔

یہ خاص طور پر LazyColumn اور LazyGrid کے لیے اہم ہے، جہاں استعمال کنندہ سکرول کرتا ہے تو آئٹمز لگاتار بنتی اور تباہ ہوتی ہیں۔ DisposableEffect کے بغیر، نظر آنے والے علاقے سے غائب ہونے والا ہر آئٹم ایک فعال رکابیتی چھوڑ جائے گا۔ DisposableEffect کے ساتھ، ان لوڈ کیے گئے ہر آئٹم کے لیے onDispose بلایا جاتا ہے، اس بات کی ضمانت دیتا ہوئے کہ آئٹم کے سکرین چھوڑنے کے فوری بعد وسائل آزاد ہو جاتے ہیں۔

Android Performance Patterns (Google, 2025) کے مطابق، تمام مقامی رکابیتیوں کے لیے DisposableEffect کا استعمال لائف سائکل callback کے ذریعے دستی انتظام کے مقابلے میں Compose ایپلیکیشنز میں میموری لیکس کی تعداد میں 60–70% کمی کرتا ہے۔ سسٹم خود اس لمحے کو ٹریک کرتا ہے جب کمپونینٹ کمپوزیشن چھوڑتا ہے اور هانگامی سکرین بند ہونے پر بھی onDispose کے اگزیکیوشن کی ضمانت دیتا ہے۔

وسیلہDisposableEffect کیا کرتا ہےDisposableEffect کے بغیر
BroadcastReceiverregister + onDispose → unregisterریسیور فعال رہتا ہے
SensorManagerregisterListener + onDispose → unregisterListenerسینسر ڈیٹا بھیجتا رہتا ہے
Observable (Flow نہیں)subscribe + onDispose → unsubscribeCallback حوالہ رکھتا ہے
TextureView / SurfaceViewsetCallback + onDispose → removeCallbackCallback لیک
Socket / Channelopen + onDispose → closeکنیکشن کھلا رہتا ہے

DisposableEffect کے ذریعے سینسرز کی رکابیتی

DisposableEffect کے استعمال کی سب سے واضح مثالوں میں سے ایک آلے سینسرز (ایکسیلرومیٹر، جائروسکوپ، میگنیٹومیٹر) کے ساتھ کام کرنا ہے۔ سینسرز کو کام کے اختتام پر لازمی طور پر رجسٹریشن منسوخ کرنے کی ضرورت ہوتی ہے، ورنہ وے سکرین بند ہونے کے بعد بھی بیٹری کی طاقت استعمال کرتے رہتے ہیں اور ڈیٹا بھیجتے رہتے ہیں۔

عملی مثال: ایک زاویہ میاپ ایپلیکیشن۔ DisposableEffect(Unit) کمپونینٹ کے ظاہر ہونے پر ایک ایکسیلرومیٹر سننے والے کی رجسٹریشن کرتا ہے اور onDispose میں رجسٹریشن منسوخ کرتا ہے۔ سینسر کا ڈیٹا mutableStateOf کے ذریعے حالت میں بھیجا جاتا ہے، جو خودکار طور پر UI کو اپڈیٹ کرتا ہے۔ اگر سکرین LazyColumn میں سکرول ہوتی ہے اور آئٹم غائب ہو جاتا ہے، onDispose فورا چل جاتا ہے — سینسر اس آئٹم کے لیے ڈیٹا بھیجنا بند کر دیتا ہے۔

سینسر کی قسم بدلتے وقت (مثال کے طور پر، ایکسیلرومیٹر سے جائروسکوپ میں)، sensorType کنجی بدلتی ہے، onDispose پرانی رکابیتی منسوخ کرتا ہے، اور نءی DisposableEffect بلاک نءے سینسر کی رجسٹریشن کرتا ہے۔ کنجیوں کے بغیر، آپ کو دستی طور پر چیک کرنا ہوگا کہ کون سا سینسر پہلے رجسٹر کیا گیا تھا اور صحیح سننے والے کے ساتھ unregisterListener بلانا ہوگا — جو غلطی کا شکار ہے۔

kotlin
@Composable
fun SensorReadingScreen(sensorType: Int) {
    val context = LocalContext.current
    val sensorManager = context.getSystemService(Context.SENSOR_SERVICE) as SensorManager
    var sensorValue by remember { mutableStateOf(0f) }
    
    DisposableEffect(sensorType) {
        val sensor = sensorManager.getDefaultSensor(sensorType)
        val listener = SensorEventListener { event, _ ->
            sensorValue = event.values[0]
        }
        sensorManager.registerListener(listener, sensor, SensorManager.SENSOR_DELAY_NORMAL)
        
        onDispose {
            sensorManager.unregisterListener(listener)
        }
    }
    
    Text("قیمت: $sensorValue")
}

DisposableEffect کے ذریعے BroadcastReceiver کی رجسٹریشن

BroadcastReceiver ایک API کی ایک کلاسیکی مثال ہے جسے ایک لازمی register / unregister جوڑے کی ضرورت ہوتی ہے۔ ایک Compose ایپلیکیشن میں، DisposableEffect ایک مخصوص سکرین کی زندگی کے دوران ایک ریسیور کی رجسٹریشن کے لیے موزوں ہے۔ سکرین میں داخل ہونے پر، مطلوبہ IntentFilter کے ساتھ ایک BroadcastReceiver رجسٹر کیا جاتا ہے؛ باہر نکلتے وقت، یہ onDispose میں خودکار طور پر منسوخ ہو جاتا ہے۔

ایک معمولی منظر نیٹورک اسٹیٹس مونیٹرنگ ہے۔ DisposableEffect ConnectivityManager کے لیے ایک ریسیور رجسٹر کرتا ہے جو نیٹورک کنیکٹویٹی میں تبدیلیوں کے بارے میں آگاہ کرتا ہے۔ حالت بدلنے پر (WiFi / موبائل ڈیٹا / کئی نیٹورک نہیں)، composable حالت اپڈیٹ ہوتی ہے اور UI مناسب اشارہ ڈیسپلے کرتا ہے۔ جب سکرین بند ہوتی ہے، onDispose رجسٹریشن منسوخ کرنے کی ضمانت دیتا ہے — چاہے ایپ بیک گراؤنڈ میں چلی جائے۔

RECEIVER_EXPORTED / RECEIVER_NOT_EXPORTED فلیگ (Android 14+) کے ساتھ ContextCompat.registerReceiver استعمال کرنے والے ریسیورز کے لیے، DisposableEffect کا استعمال لازمی ہو جاتا ہے کیونکہ سسٹم کو ریسیور کے دائرے کی واضح تعیین کی ضرورت ہوتی ہے۔ DisposableEffect اس بات کی ضمانت دیتا ہے کہ دائرہ سکرین کی زندگی تک محدود ہے، جو Android کے نئے ورژنز کی حفاظتی ضرورتات کے ساتھ هم آہنگ ہے۔

kotlin
@Composable
fun NetworkStatusBanner() {
    val context = LocalContext.current
    var isConnected by remember { mutableStateOf(true) }
    
    DisposableEffect(Unit) {
        val receiver = BroadcastReceiver { _, _ ->
            val cm = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
            isConnected = cm.getActiveNetwork() != null
        }
        IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION).let { filter ->
            context.registerReceiver(receiver, filter)
        }
        
        onDispose {
            context.unregisterReceiver(receiver)
        }
    }
    
    if (!isConnected) { ... }
}

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

پہلی سنگین غلطی onDispose کول کی غیرموجودگی ہے۔ DisposableEffect بلاک کے اندر کوڈ کو onDispose بلانا چاہیے، ورنہ کامپائلیشن کی غلطی ہوگی۔ تاہم، ڈیولپر کبھی کبھی onDispose کو شرط میں رکھ کر اسے بچانے کی کوشش کرتے ہیں: if (condition) { onDispose { ... } }۔ یہ کوڈ کامپائل ہو جائے گا، لیکن اگر شرط پوری نہیں ہوتی تو onDispose رجسٹر نہیں ہوگا — وسیلہ کبھی آزاد نہیں ہوگا۔

دوسری غلطی غیر سنکرونس کارروائیوں کے لیے DisposableEffect کا استعمال ہے۔ چونکہ DisposableEffect سنکرونس ہے، آپ اس کے اندر delay() یا await() کول نہیں لکھ سکت۔۔ اگر آپ کو بعد میں صفائی کے ساتھ غیر سنکرونس آغاز کی ضرورت ہے، LaunchedEffect (ڈیٹا لوڈنگ کے لیے) اور DisposableEffect (مقامی وسائل کی سیٹوپ/صفائی کے لیے) کا سنگت استعمال کریں، یا rememberCoroutineScope کے ساتھ ایک علیحدہ میکانزم استعمال کریں۔

تیسری غلطی remember کے بغیر DisposableEffect کے اندر نئے آبجیکٹس بنانا ہے۔ اگر آبجیکٹس (سینسر، listener، receiver) ہر کول پر افیکٹ کے اندر بنائے جاتے ہیں اور کنجیاں اکسر بدلتی رہتی ہیں، تو اس سے ضرورت سے زائد آبجیکٹس بنتے ہیں اور کوڑا کٹھر ہوتا ہے۔ بہتر ہے کہ آبجیکٹ بنانے کو DisposableEffect کے باہر remember یا remember { ... } میں لے جائیں، اور افیکٹ کے اندر صرف انہیں رجسٹر اور منسوخ کریں۔

اکثر پوچے جانے والے سوالات

DisposableEffect اور LaunchedEffect میں کیا فرق ہے؟

DisposableEffect سنکرونس کام کرتا ہے اور وسائل کی واضح صفائی کے لیے onDispose فراہم کرتا ہے۔ LaunchedEffect ایک کوروٹین میں غیر سنکرونس کام کرتا ہے اور اسے خودکار طور پر اس وقت منسوخ کر دیتا ہے جب کنجی بدلتی ہے یا کمپوزیشن چھوڑتی ہے۔ اگر کسی وسیلے کو صفائی کے طریقے (close, unregister, dispose) کی ضرورت ہو — DisposableEffect استعمال کریں۔ اگر کارروائی ایک suspend فنکشن ہے — LaunchedEffect استعمال کریں۔

کیا DisposableEffect میں onDispose بلاک لازمی ہے؟

جی ہاں، onDispose لازمی ہے — Kotlin کامپائلر DisposableEffect بلاک کے اندر اسے بلانے کا تقاضہ کرتا ہے۔ اگر آپ onDispose نہیں بلاتے، تو کوڈ کامپائل نہیں ہوگا۔ یہ جان بوجہ کیا گیا ہے تاکہ ڈیولپر بھول نا سکیں اور اس بات کی ضمانت دی جا سکے کہ کمپوزیشن چھوڑتے وقت ہر کھولا وسیلہ صحیح طور پر بند ہوگا۔

DisposableEffect کے اندر غلطیوں کو کیسے ہینڈل کیا جائے؟

DisposableEffect بلاک کے اندر try-catch استعمال کریں۔ اگر وسیلے کی رجسٹریشن ایک استثنا پھینک سکتی ہے (مثال کے طور پر، سینسر نہیں ملا)، اسے try میں لپیٹیں اور علاوہ حالت کے ذریعے UI میں غلطی کو ہینڈل کریں۔ onDispose کو آغاز کی کامیابی سے آزاد بلایا جانا چاہیے — اسے finally بلاک میں یا try سیکشن کے آخر میں رکھیں۔

کیا میں Flow کی رکابیتی کے لیے DisposableEffect استعمال کر سکتا ہوں؟

سفارش نہیں کی جاتی۔ Flow کے لیے، collectLatest کے ساتھ LaunchedEffect یا Lifecycle.repeatOnLifecycle کے ساتھ .collectAsState() کا استعمال کرنا بہتر ہے۔ DisposableEffect suspend فنکشنز کی حمایت نہیں کرتا، لہذا اس کے اندر Flow کی رکابیتی کے لیے CoroutineScope کے ذریعے ایک علیحدہ کوروٹین شروع کرنے کی ضرورت ہوگی، جو کوڈ کو پیچیدہ کرتا ہے اور لیڡز کے خطرے کو بڑھاتا ہے۔

ایک composable میں کتنے DisposableEffect ہو سکتے ہیں؟

کئی حدود نہیں ہیں، لیکن متعلق وسائل کو ایک DisposableEffect میں اندر متعدد کارروائیوں اور ایک onDispose کے ساتھ گروپ کرنے کی سفارش کی جاتی ہے۔ اگر وسائل آزاد ہیں (مثال کے طور پر، سینسر اور BroadcastReceiver)، تو انہیں مختلف کنجیوں کے ساتھ علیحدہ DisposableEffects میں تقسیم کرنا بہتر ہے — یہ ڈیباگنگ کو آسان بناتا ہے اور ایک کنجی بدلنے پر سب وسائل کی نامناسب دوبارہ تخلیق کو روکتا ہے۔

خلاصہ

  • DisposableEffect — onDispose کے ذریعے گارنٹی شدہ صفائی کے ساتھ سنکرونس آغاز کے لیے Jetpack Compose side-effect API۔
  • onDispose — لازمی بلاک جو کمپوزیشن چھوڑتے وقت یا کنجی بدلتے وقت چلتا ہے، میموری لیکس کو روکتا ہے۔
  • کنجیاں — جب کنجی بدلتی ہے، پہلے onDispose پرانی قیمت کے لیے چلتا ہے، پھر نئی قیمت کے ساتھ دوبارہ آغاز ہوتا ہے۔
  • سنکرونس — DisposableEffect سنکرونس چلتا ہے؛ اس کے اندر suspend فنکشنز دستیاب نہیں ہیں۔
  • معمولی مناظر — BroadcastReceiver، سینسرز، مقامی سننے والے، callback-based لائبریریز، AndroidView انٹیگریشن۔
  • لیڡز — DisposableEffect لائف سائکل callback کے ذریعے دستی انتظام کے مقابلے لیڡز کی تعداد میں 60–70% کمی کرتا ہے۔
  • غلطیاں — اہم خطرات: شرطی onDispose کول، غیر سنکرونس کارروائیوں کے لیے استعمال، افیکٹ کے اندر remember کے بغیر آبجیکٹس بنانا۔

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

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

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

مزید پڑھیں