LifecycleOwner — Android Jetpack لائبریری کا ایک اہم انٹرفیس ہے جو اعلان کرتا ہے کہ کسی آبجیکٹ کا ایک لائف سائیکل ہے اور getLifecycle() طریقہ کے ذریعے اس تک رسائی فراہم کرتا ہے۔ یہ جدید Android ایپلیکیشنز کے اجزاء کی آرکیٹیکچر کی بنیاد ہے، جو لائف سائیکل مینجمنٹ کی منطق کو Activity یا Fragment کے مخصوص نفاذ سے الگ کرنے کی اجازت دیتا ہے۔ Google I/O 2024 کے اعداد و شمار کے مطابق، Android پر نئے منصوبوں میں سے 85% سے زیادہ LifecycleOwner کا استعمال سبسکرپشنز کے انتظام اور میموری لیک کو روکنے کے لیے کرتے ہیں۔ یہ انٹرفیس LiveData، ViewModel اور دیگر Jetpack اجزاء کی بنیاد ہے، جو جزو کی فعال حالت میں صرف محفوظ کوڈ پر عمل درآمد کو یقینی بناتا ہے۔
اہم نکات
LifecycleOwner — androidx.lifecycle پیکیج کا ایک انٹرفیس ہے جس میں ایک واحد طریقہ getLifecycle() ہے جو Lifecycle آبجیکٹ لوٹاتا ہے۔ یہ آبجیکٹ جزو کی موجودہ حالت (CREATED, STARTED, RESUMED, DESTROYED) کو ٹریک کرتا ہے اور تبدیل ہونے پر تمام سبسکرائب شدہ مبصرین کو مطلع کرتا ہے۔ LifecycleOwner آرکیٹیکچر اجزاء کا حصہ ہے اور lifecycle-runtime لائبریری میں شامل ہے۔
انٹرفیس کا بنیادی کام لائف سائیکل تک رسائی کو معیاری بنانا ہے۔ Jetpack سے پہلے، ڈویلپرز onStart میں دستی سبسکرپشن اور onStop میں ان سبسکرپشن استعمال کرتے تھے، جس سے کوڈ کی نقل اور غلطیاں ہوتی تھیں۔ LifecycleOwner اس مسئلے کو حل کرتا ہے، تمام Android اجزاء کے لیے ایک متحد طریقہ کار فراہم کرتا ہے۔ لائف سائیکل کے طریقوں کو واضح طور پر کال کرنے کے بجائے، ڈویلپر ایک بار Lifecycle میں سبسکرائب ہوتا ہے اور اطلاعات خودکار طور پر آتی ہیں۔
انٹرفیس Kotlin میں ایک واحد تجریدی طریقہ کے ساتھ ایک فعالی انٹرفیس کے طور پر اعلان کیا گیا ہے:
interface LifecycleOwner {
val lifecycle: Lifecycle
}
انٹرفیس کی فعالی نوعیت کی وجہ سے، اسے ڈیلیگیٹ یا لیمبڈا کا استعمال کرتے ہوئے آسانی سے نافذ کیا جا سکتا ہے۔ یہ خاص طور پر Custom Views اور ViewModel کلاسز بنانے کے لیے آسان ہے جنہیں میزبان کے لائف سائیکل تبدیلیوں پر ردعمل دینا ہوتا ہے۔ getLifecycle() سے حاصل کردہ Lifecycle آبجیکٹ سبسکرپشنز کے انتظام کے لیے addObserver اور removeObserver طریقے فراہم کرتا ہے۔
LifecycleOwner دو اہم کلاسز کے ساتھ مل کر کام کرتا ہے: Lifecycle اور LifecycleObserver۔ Lifecycle جزو کی موجودہ حالت کو enum State (INITIALIZED, CREATED, STARTED, RESUMED, DESTROYED) کے طور پر ذخیرہ کرتا ہے اور ان کے درمیان منتقلی کو ٹریک کرتا ہے۔ جب حالت تبدیل ہوتی ہے، Lifecycle تمام رجسٹرڈ مبصرین کو مطلع کرتا ہے، متعلقہ تشریح شدہ طریقوں کو کال کرتا ہے۔ اس طریقہ کار کو "lifecycle-aware" کہا جاتا ہے — کوڈ صرف اس وقت عمل میں آتا ہے جب جزو مناسب حالت میں ہو۔
ایونٹ کی ترسیل کا طریقہ کار Observer پیٹرن پر مبنی ہے۔ LifecycleOwner Observable کے طور پر کام کرتا ہے، اور LifecycleObserver کا نفاذ Observer کے طور پر کام کرتا ہے۔ Activity یا Fragment جب اپنی حالت تبدیل کرتا ہے (onCreate → onStart → onResume → onPause → onStop → onDestroy)، تو داخلی طریقہ کار ReportFragment کے ذریعے Lifecycle کو مطلع کرتا ہے، جو AndroidX سسٹم میں خودکار طور پر شامل ہوتا ہے۔ ڈویلپر کو Lifecycle کے طریقوں کو دستی طور پر کال کرنے کی ضرورت نہیں ہے — سب کچھ خودکار طور پر ہوتا ہے۔
| Lifecycle حالت | واقعہ | Android لائف سائیکل طریقہ |
|---|---|---|
| INITIALIZED | — | onCreate سے پہلے |
| CREATED | ON_CREATE | onCreate |
| STARTED | ON_START | onStart |
| RESUMED | ON_RESUME | onResume |
| STARTED | ON_PAUSE | onPause |
| CREATED | ON_STOP | onStop |
| DESTROYED | ON_DESTROY | onDestroy |
ایک اہم تفصیل: Lifecycle اس بات کی ضمانت دیتا ہے کہ ON_STOP اور ON_DESTROY واقعات عمل کے کریش ہونے کی صورت میں بھی پہنچائے جائیں گے۔ یہ LifecycleOwner کو اہم وسائل کو آزاد کرنے کے لیے ایک قابل اعتماد ٹول بناتا ہے۔ عام حالت کو محفوظ کرنے کے لیے ViewModel میں SavedStateHandle استعمال کرنے کی سفارش کی جاتی ہے، لیکن LifecycleOwner بنیادی حفاظت کی سطح فراہم کرتا ہے۔
LifecycleOwner کے واقعات کو سبسکرائب کرنے کے دو طریقے ہیں: تشریحات کے ساتھ کلاسک LifecycleObserver اور واضح طریقوں کے ساتھ جدید DefaultLifecycleObserver۔ دوسرا طریقہ Google 2022 سے تجویز کرتا ہے کیونکہ یہ بہتر قسم کی حفاظت فراہم کرتا ہے اور تشریحی طریقہ میں استعمال ہونے والی عکاسی (reflection) سے بچتا ہے۔ DefaultLifecycleObserver کے لیے Java 8+ یا Kotlin کی ضرورت ہے اور یہ نئے منصوبوں کے لیے ترجیحی ہے۔
DefaultLifecycleObserver کے ذریعے سبسکرپشن کی مثال:
class MyObserver : DefaultLifecycleObserver {
override fun onStart(owner: LifecycleOwner) {
// GPS ٹریکنگ صرف اس وقت شروع کریں جب جزو فعال ہو
startLocationUpdates()
}
override fun onStop(owner: LifecycleOwner) {
// پس منظر میں منتقلی پر محفوظ روک
stopLocationUpdates()
}
}
// کنیکشن:
lifecycleOwner.lifecycle.addObserver(MyObserver())
DefaultLifecycleObserver کا ہر طریقہ پیرامیٹر کے طور پر LifecycleOwner لیتا ہے۔ یہ مبصر کو الگ سے منتقل کیے بغیر چلنے والے جزو کے سیاق و سباق تک رسائی کی اجازت دیتا ہے۔ یہ طریقہ کوڈ کو زیادہ ماڈیولر اور قابل جانچ بناتا ہے — Observer Activity یا Fragment کے مخصوص نفاذ پر منحصر نہیں ہوتا، بلکہ LifecycleOwner تجرید کے ساتھ کام کرتا ہے۔
@OnLifecycleEvent تشریح استعمال کرنے والا پرانا طریقہ اب بھی پرانے منصوبوں میں پایا جاتا ہے، لیکن نئے کوڈ کے لیے اس کا استعمال تجویز نہیں کیا جاتا۔ تشریحات پر کارروائی کے لیے درکار عکاسی اضافی بوجھ ڈالتی ہے اور غلطیوں کا باعث بن سکتی ہے جو مرتب کرنے کے وقت پکڑی نہیں جاتیں۔ Google سرکاری طور پر DefaultLifecycleObserver میں منتقلی کا مشورہ دیتا ہے۔
// پرانا طریقہ — نئے منصوبوں کے لیے تجویز نہیں کیا جاتا
class MyLegacyObserver : LifecycleObserver {
@OnLifecycleEvent(Lifecycle.Event.ON_START)
fun onStart() {
startLocationUpdates()
}
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
fun onStop() {
stopLocationUpdates()
}
}
تشریحی طریقہ کی ایک اہم کمی ہے: Observer کی زندگی بھر کے کنٹرول کی کمی۔ اگر ڈویلپر LifecycleOwner کی تباہی پر Observer کو ان سبسکرائب کرنا بھول جاتا ہے، تو Observer آبجیکٹ کوڑے دان جمع کرنے والے کی کال تک میموری میں رہتا ہے۔ DefaultLifecycleObserver اس مسئلے کو حل کرتا ہے — Observer Lifecycle سے منسلک ہوتا ہے اور DESTROYED حالت میں منتقلی پر خودکار طور پر ان سبسکرائب ہو جاتا ہے۔
AppCompat 1.1.0 اور AndroidX Fragment 1.2.0 سے، AppCompatActivity یا Fragment سے وراثت پانے والی تمام Activity اور Fragment خودکار طور پر LifecycleOwner بن جاتے ہیں۔ اس کا مطلب ہے کہ getLifecycle() طریقہ بطور ڈیفالٹ دستیاب ہے اور لائف سائیکل کے واقعات کی سبسکرپشن اضافی ترتیب کے بغیر کام کرتی ہے۔ ڈویلپر کو صرف Activity یا Fragment میں کہیں سے بھی lifecycle.addObserver() کال کرنے کی ضرورت ہے۔
Activity میں LifecycleOwner انضمام کی مثال دیکھتے ہیں:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
lifecycle.addObserver(LocationObserver(this))
}
}
اس مثال میں، lifecycle ایک extension property ہے جو AndroidX Activity کی بدولت دستیاب ہے۔ LocationObserver مبصر خودکار طور پر Activity کے شروع (ON_START) اور رکنے (ON_STOP) کے بارے میں اطلاعات حاصل کرے گا۔ اسکرین گھمانے پر، Observer ON_DESTROY اور پھر ON_CREATE کے بارے میں مطلع کیا جاتا ہے، جو اضافی کوڈ کے بغیر ترتیب تبدیلیوں کو درست طریقے سے سنبھالنے کی اجازت دیتا ہے۔
Fragment انٹرفیس کے ذریعے LifecycleOwner کو نافذ کرتا ہے، اور اس کا Lifecycle والدین Activity کے بجائے Fragment کی لائف سائیکل سے منسلک ہوتا ہے۔ یہ اہم ہے: Fragment کا Lifecycle DESTROYED میں اس وقت منتقل ہوتا ہے جب Fragment ٹرانزیکشن سے ہٹا دیا جاتا ہے، جبکہ Activity RESUMED حالت میں رہ سکتی ہے۔ یہ فرق Observer کو ہر جزو کی لائف سائیکل میں علیحدہ علیحدہ سبسکرائب کرنے کی اجازت دیتا ہے۔
class MyFragment : Fragment() {
private val uiStateObserver = UiStateObserver()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
lifecycle.addObserver(uiStateObserver)
}
}
Fragment میں LifecycleOwner استعمال کرنے کا ایک اہم فائدہ Fragment کے DESTROYED میں منتقل ہونے پر خودکار ان سبسکرپشن ہے۔ یہ خاص طور پر ViewPager کے لیے اہم ہے، جہاں Fragment متحرک طور پر بنائے اور تباہ کیے جا سکتے ہیں۔ اس منظر نامے میں دستی سبسکرپشن کا انتظام انتہائی پیچیدہ اور غلطی کا شکار ہوگا۔
LifecycleOwner انٹرفیس کسی بھی کلاس میں نافذ کیا جا سکتا ہے جس کا ایک لائف سائیکل ہے۔ یہ Custom Views، Services اور بعض آرکیٹیکچرل حلوں میں ViewModel کے لیے بھی مفید ہے۔ Google معاون کلاس LifecycleRegistry فراہم کرتا ہے جو Lifecycle کی حالت کا انتظام کرتی ہے اور واقعات پیدا کرتی ہے۔ جزو کی حالت تبدیل ہونے پر ڈویلپر کو LifecycleRegistry کے متعلقہ طریقوں کو دستی طور پر کال کرنے کی ضرورت ہے۔
Custom View میں LifecycleOwner کے نفاذ کی مثال:
class MyCustomView(
context: Context,
attrs: AttributeSet?
) : FrameLayout(context, attrs), LifecycleOwner {
private val lifecycleRegistry = LifecycleRegistry(this)
override val lifecycle: Lifecycle
get() = lifecycleRegistry
fun onStart() {
lifecycleRegistry.setCurrentState(Lifecycle.State.STARTED)
}
fun onStop() {
lifecycleRegistry.setCurrentState(Lifecycle.State.CREATED)
}
}
اس مثال میں، LifecycleRegistry حالت کے ذخیرہ کے طور پر کام کرتا ہے۔ onStart/onStop طریقوں کو والدین کے جزو (مثلاً Activity) کے ذریعے کال کیا جانا چاہیے جب Custom View نظر آتا ہے یا چھپایا جاتا ہے۔ LifecycleRegistry خودکار طور پر حالتوں کے درمیان منتقلی کے لیے ضروری واقعات کا حساب لگاتا ہے اور تمام سبسکرائب شدہ Observer کو مطلع کرتا ہے۔
اپنے LifecycleOwner کو نافذ کرتے وقت اصول پر عمل کرنا ضروری ہے: LifecycleRegistry کی حالت کو متعلقہ لائف سائیکل طریقہ میں سب سے آخر میں اپ ڈیٹ کیا جانا چاہیے، دیگر تمام کارروائیوں کے بعد۔ یہ اس بات کو یقینی بناتا ہے کہ Observer کو اطلاع اس وقت ملتی ہے جب جزو پہلے سے نئی حالت کے لیے مکمل طور پر تیار ہو۔ متبادل کے طور پر LifecycleRegistry.createUnsafe کا استعمال بھی ممکن ہے، لیکن تھریڈز کے ساتھ احتیاط کی ضرورت ہے۔
LifecycleOwner کئی اہم Android Jetpack اجزاء کی بنیاد ہے۔ LiveData فعال حالت کا تعین کرنے اور جزو کی تباہی پر خودکار ان سبسکرپشن کے لیے LifecycleOwner کا استعمال کرتا ہے۔ ViewModel براہ راست LifecycleOwner کو نافذ نہیں کرتا لیکن SavedStateHandle کے ذریعے Lifecycle حاصل کر سکتا ہے۔ Navigation Component NavBackStackEntry میں سبسکرپشنز کے انتظام کے لیے LifecycleOwner کا استعمال کرتا ہے۔ اس باہمی تعلق کو سمجھنا ایک مضبوط بنیاد پر ایپلیکیشن آرکیٹیکچر بنانے میں مدد کرتا ہے۔
LiveData کا LifecycleOwner کے ساتھ تعامل:
class ExampleActivity : AppCompatActivity() {
private val viewModel: ExampleViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
viewModel.userData.observe(this) { data ->
// this — LifecycleOwner (Activity)
// کوڈ صرف اس وقت عمل میں آتا ہے جب Activity RESUMED حالت میں ہو
updateUI(data)
}
}
}
LiveData کو observe() طریقہ میں LifecycleOwner کی ضرورت ہے کیونکہ یہ اس بات کی ضمانت دیتا ہے کہ UI اپ ڈیٹ صرف فعال حالت میں ہوں گے۔ اگر Activity پس منظر میں ہے، LiveData آخری قیمت رکھتا ہے لیکن Observer کو مطلع نہیں کرتا۔ RESUMED میں واپسی پر، Observer اضافی نیٹ ورک یا ڈیٹا بیس کی درخواستوں کے بغیر موجودہ قیمت حاصل کرتا ہے۔
DataBinding بھی observable فیلڈز کو Activity یا Fragment کی لائف سائیکل سے منسلک کرنے کے لیے LifecycleOwner کا استعمال کرتا ہے۔ یہ ViewModel + DataBinding کے امتزاج میں میموری لیک سے بچنے کی اجازت دیتا ہے — LifecycleOwner کی تباہی پر تمام سبسکرپشنز خودکار طور پر صاف ہو جاتی ہیں۔ یہ طریقہ کوڈ کو اعلانیہ اور محفوظ بناتا ہے۔
LifecycleOwner کے صحیح استعمال کے لیے کئی اہم اصولوں پر عمل کرنا ضروری ہے۔ پہلا اور سب سے اہم: ہمیشہ onCreate/onViewCreated میں Observer کو سبسکرائب کریں، بعد میں نہیں۔ یہ اس بات کو یقینی بناتا ہے کہ Observer کو Lifecycle کی ابتدائی حالت (onCreate کے بعد CREATED) ملے اور واقعات سے محروم نہ ہو۔ دوسرا اصول: تمام نئے منصوبوں کے لیے تشریحی طریقہ کے بجائے DefaultLifecycleObserver استعمال کریں۔
کوروٹینز اور LifecycleOwner کے ساتھ کام کرنے کا جدید طریقہ — repeatOnLifecycle توسیع:
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED) {
viewModel.flow.collect { value ->
updateUI(value)
}
}
}
یہ پیٹرن اس بات کی ضمانت دیتا ہے کہ Flow پر collect صرف STARTED یا RESUMED حالت میں فعال ہے۔ STOPPED میں منتقلی پر، جمع کرنا خودکار طور پر منسوخ ہو جاتا ہے اور STARTED میں واپسی پر دوبارہ شروع ہوتا ہے۔ repeatOnLifecycle Fragment میں Flow سے دستی ان سبسکرپشن کی جگہ لیتا ہے اور UI اجزاء میں متضاد ڈیٹا اسٹریمز کے ساتھ کام کرنے کے لیے Google کا تجویز کردہ طریقہ ہے۔
ایک اور اہم مشورہ: لائف سائیکل سے غیر متعلق منطق کے لیے LifecycleObserver کا زیادہ استعمال نہ کریں۔ اگر کسی جزو کو کسی خاص حالت میں کارروائی کرنی ہے لیکن تباہی پر ان سبسکرپشن کی ضرورت نہیں ہے، تو onStart/onStop میں واضح طریقہ کال استعمال کرنا بہتر ہے۔ LifecycleObserver طویل عرصے تک چلنے والے اجزاء (LocationListener, SensorManager) کے لیے موزوں ہے جہاں دستی سبسکرپشن کا انتظام پیچیدہ اور غلطی کا شکار ہے۔
اکثر پوچھے گئے سوالات
LifecycleOwner — ایک انٹرفیس ہے جو اعلان کرتا ہے کہ کسی آبجیکٹ کا ایک لائف سائیکل ہے۔ Lifecycle — ایک کلاس ہے جو موجودہ حالت ذخیرہ کرتی ہے اور Observer کا انتظام کرتی ہے۔ LifecycleOwner getLifecycle() کے ذریعے Lifecycle فراہم کرتا ہے۔
نہیں، Lifecycle DESTROYED میں منتقلی پر خودکار طور پر تمام Observer کو ان سبسکرائب کر دیتا ہے۔ یہ LifecycleOwner کے اہم فوائد میں سے ایک ہے — ڈویلپر کو onDestroy میں دستی طور پر removeObserver کال کرنے کی ضرورت نہیں۔
Fragment AndroidX فریگمنٹ انٹرفیس کے ذریعے LifecycleOwner کو نافذ کرتا ہے۔ اس کا Lifecycle Activity سے الگ Fragment کی لائف سائیکل سے منسلک ہوتا ہے۔ یہ Observer کو والدین Activity کے بجائے Fragment کے واقعات پر ردعمل دینے کی اجازت دیتا ہے۔
ہاں، اس کے لیے LifecycleRegistry استعمال کیا جاتا ہے۔ Custom View کو LifecycleOwner انٹرفیس نافذ کرنا چاہیے اور مرئیت یا ونڈو سے منسلک ہونے کی تبدیلی پر LifecycleRegistry کی حالت کو دستی طور پر اپ ڈیٹ کرنا چاہیے۔
LifecycleOwner ایک مختلف مسئلہ حل کرتا ہے: لائف سائیکل کے واقعات کی سبسکرپشن کا انتظام، کوروٹین کی منسوخی نہیں۔ کوروٹینز کے لیے lifecycleScope استعمال کیا جاتا ہے، جو LifecycleOwner کی تباہی پر چلنے والی کوروٹینز کو خودکار طور پر منسوخ کرتا ہے۔
خلاصہ
ہم ایک موبائل ایپلیکیشن ٹرنکی تیار کریں گے
IT Sectr 2017 سے اسٹارٹ اپس اور کاروبار کے لیے iOS اور Android ایپلیکیشنز بناتا ہے۔ ہم آپ کو مشورہ دیں گے اور بہترین حل تجویز کریں گے۔
مزید پڑھیں