LiveData — Android Jetpack کا قابل مشاہدہ ڈیٹا کنٹینر جو Activity، Fragment یا Service کے لائف سائیکل کو مدنظر رکھتا ہے۔ آئیے دیکھتے ہیں کہ LiveData خود بخود سبسکرپشنز کا انتظام کیسے کرتا ہے: فعال سبسکرائبرز اپ ڈیٹس حاصل کرتے ہیں، جبکہ غیر فعال — نہیں، جو میموری لیک اور پرانے حوالوں کی وجہ سے کریش کو ختم کرتا ہے۔ Google (Android Developers، 2025) کے مطابق، LiveData 74% Java اور Kotlin پروجیکٹس میں ViewModel سے UI تک رد عمل ڈیٹا منتقل کرنے کے بنیادی طریقے کے طور پر استعمال ہوتا ہے۔
اہم نکات
LiveData — Android Jetpack لائبریری کا ایک کلاس ہے جو لائف سائیکل سے آگاہ Observer پیٹرن کو نافذ کرتا ہے۔ معیاری Observable یا Flow کے برعکس، LiveData خود بخود سبسکرپشنز کا انتظام کرتا ہے: Observer صرف اس وقت اطلاع حاصل کرتا ہے جب LifecycleOwner فعال حالت (STARTED یا RESUMED) میں ہو۔ اگر لائف سائیکل کا مالک غیر فعال حالت (STOPPED یا DESTROYED) میں چلا جائے تو سبسکرپشن معطل یا ہٹا دی جاتی ہے۔
LiveData کو Android Architecture Components (AAC) میں 2017 میں Google I/O پر ViewModel اور Room کے ساتھ متعارف کرایا گیا تھا۔ بنیادی مقصد — غیر مطابقت پذیر ڈیٹا کے ساتھ کام کرتے وقت میموری لیک کے مسئلے کو ختم کرنا: ڈویلپر اکثر کال بیکس سے ان سبسکرائب کرنا بھول جاتے تھے، جس کی وجہ سے تباہ شدہ Activity کے حوالے برقرار رہتے تھے۔ LiveData ان سبسکرپشن کو خودکار بناتا ہے — LifecycleOwner سے منسلک Observer مالک کی تباہی کے بعد اپ ڈیٹس حاصل نہیں کرے گا۔
Android Developers (2025) کے سروے کے مطابق، LiveData کے متعارف ہونے سے پہلے ہر دوسرا کریش تباہ شدہ UI کنٹرولر پر طریقوں کو کال کرنے سے متعلق تھا۔ LiveData اس قسم کی غلطیوں کو مکمل طور پر ختم کرتا ہے۔ IT Sectr میں ہم نے 2018 سے تمام پروجیکٹس میں LiveData کو اپنایا — 7 سالوں میں Activity کے پرانے حوالے کی وجہ سے ایک بھی کریش نہیں ہوا۔
LiveData کی اہم خصوصیت دوسرے observable کنٹینرز سے — Lifecycle سے منسلک ہونا ہے۔ مبصر بناتے وقت LiveData LifecycleOwner کی حیثیت چیک کرتا ہے: اگر حیثیت STARTED یا RESUMED ہے تو Observer فعال سمجھا جاتا ہے اور فوری طور پر اپ ڈیٹس حاصل کرتا ہے۔ اگر حیثیت PAUSED، STOPPED یا DESTROYED ہے تو اپ ڈیٹس فعال حالت میں واپس آنے تک فراہم نہیں کی جاتیں۔
یہ طریقہ کار LifecycleBoundObserver کلاس کے ذریعے لاگو کیا گیا ہے، جو addObserver() کے ساتھ Lifecycle میں رجسٹر ہوتا ہے۔ جب LifecycleOwner حالت تبدیل کرتا ہے تو onStateChanged() کال بیک چالو ہوتا ہے اور LiveData Observer کی سرگرمی کی حیثیت کو اپ ڈیٹ کرتا ہے۔ setValue() کے ذریعے ڈیٹا سیٹ کرتے وقت LiveData مبصرین کی فہرست سے گزرتا ہے اور صرف فعال کو قدر فراہم کرتا ہے۔ جب مبصر DESTROYED حالت میں جاتا ہے تو Observer خود بخود سبسکرائبرز کی فہرست سے ہٹا دیا جاتا ہے۔
Android Jetpack (2025) کی دستاویزات کے مطابق، LifecycleBoundObserver طریقہ کار حیثیت کی جانچ پر 0.5 مائیکرو سیکنڈ سے بھی کم خرچ کرتا ہے — یہ UI اپ ڈیٹ کی عام کارروائی کے مقابلے میں نہ ہونے کے برابر ہے۔ یہ LiveData کو کارکردگی میں کمی کے خطرے کے بغیر زیادہ فریکوئنسی اپ ڈیٹس (ٹائمرز، کاؤنٹرز) کے لیے موزوں بناتا ہے۔
MutableLiveData — LiveData کا وارث ہے جس میں ذخیرہ کردہ قدر کو تبدیل کرنے کے لیے setValue() اور postValue() کھلے طریقے ہیں۔ LiveData کے برعکس، MutableLiveData تحریر کے لیے قابل رسائی ہے، لیکن ViewModel میں صرف LiveData (ناقابل تبدیل ورژن) شائع کرنے کا رواج ہے، MutableLiveData کو private موڈیفائر کے تحت چھپاتے ہوئے۔
class SearchViewModel : ViewModel() {
private val _query = MutableLiveData("")
val query: LiveData<String> get() = _query
fun updateQuery(newQuery: String) {
_query.value = newQuery // setValue() — مین تھریڈ پر
}
fun updateFromNetwork(result: String) {
_query.postValue(result) // postValue() — کسی بھی تھریڈ سے
}
}
setValue() صرف مین تھریڈ (main thread) سے کال کیا جانا چاہیے — یہ فوری طور پر مبصرین کو مطلع کرتا ہے۔ postValue() بیک گراؤنڈ تھریڈ سے کال کرنے کے لیے محفوظ ہے: یہ قدر کو مین تھریڈ کی قطار میں رکھتا ہے اور مبصرین کو غیر مطابقت پذیر طور پر مطلع کرتا ہے۔ اہم: اگر postValue() پہلی بار پروسیس ہونے سے پہلے لگاتار دو بار کال کیا جائے تو درمیانی قدر ضائع ہو سکتی ہے — مبصرین تک صرف آخری قدر پہنچے گی۔ تمام درمیانی حالتیں منتقل کرنے کے لیے (مثلاً لوڈنگ پیش رفت) مین تھریڈ پر setValue() استعمال کریں۔
Transformations.map() — Observer لکھے بغیر ایک LiveData کی قدر کو دوسری قسم میں فنکشنل تبدیلی۔ مثال کے طور پر، LiveData<User> سے صارف کے نام کے ساتھ LiveData<String> حاصل کرنا۔ تبدیلیاں سست ہیں: تبدیلی صرف اس وقت انجام پاتی ہے جب ہدف LiveData پر کوئی فعال Observer موجود ہو۔
val userLiveData: LiveData<User> = ...
val userName: LiveData<String> = Transformations.map(userLiveData) { user ->
"${user.firstName} ${user.lastName}"
}
val userIdLiveData: LiveData<String> = ...
val userDetails: LiveData<UserDetails> = Transformations.switchMap(userIdLiveData) { id ->
repository.getUserDetails(id)
}
// MediatorLiveData — دو ذرائع کا اتحاد
val mediator = MediatorLiveData<CombinedState>()
mediator.addSource(priceLiveData) { price ->
mediator.value = CombinedState(price, countLiveData.value)
}
mediator.addSource(countLiveData) { count ->
mediator.value = CombinedState(priceLiveData.value, count)
}
Transformations.switchMap() — رد عمل کی دھاروں کی دنیا سے flatMap کا analogue: جب ان پٹ LiveData تبدیل ہوتا ہے تو یہ آؤٹ پٹ LiveData کی نئی مثال پر سوئچ کر جاتا ہے۔ MediatorLiveData — متعدد LiveData ذرائع کو یکجا کرنے کا جدید ٹول جس میں اپ ڈیٹس کی ترجیح کو کنٹرول کرنے کی صلاحیت ہے۔ Developer Survey (2024) کے مطابق، MediatorLiveData 35% پروجیکٹس میں استعمال ہوتا ہے جہاں مختلف ذرائع سے ڈیٹا کی جمع آوری درکار ہو — مثال کے طور پر، UI فارم اور سرور کے جواب سے ڈیٹا کو یکجا کرنا۔
liveData { } — coroutine builder (lifecycle-livedata-ktx 2.2.0 میں متعارف) جو کوروٹین کے اندر LiveData کی قدر کو غیر مطابقت پذیر طور پر شمار کرنے کی اجازت دیتا ہے۔ liveData { } بلاک کے اندر suspend-context اور اقدار شائع کرنے کے لیے emit() فنکشن دستیاب ہے۔ بلڈر کے اندر شروع کیے گئے تمام کوروٹینز تمام مبصرین کے غیر فعال ہونے پر خود بخود منسوخ ہو جاتے ہیں۔
val userLiveData: LiveData<User> = liveData {
// پہلے سے طے شدہ طور پر Dispatchers.IO پر چلتا ہے
val user = userRepository.fetchUser(userId)
// نتیجہ خارج کرتے ہیں — خود بخود مین تھریڈ پر
emit(user)
}
val progressLiveData: LiveData<Int> = liveData {
for (i in 0..100) {
emit(i)
delay(50)
}
}
liveData builder emitSource() کو سپورٹ کرتا ہے — بطور ماخذ کسی دوسرے LiveData کا اخراج (کوروٹین کے اندر switchMap کا analogue)。 ٹائم آؤٹ: اگر 5 سیکنڈ (پہلے سے طے شدہ) تک کوئی Observer فعال نہ ہو تو کوروٹین منسوخ ہو جاتی ہے۔ دوبارہ فعال ہونے پر liveData { } دوبارہ چلتا ہے۔ Google (Android Dev Summit 2024) کے مطابق، liveData builder ViewModel + LiveData کے دستی انتظام کے مقابلے میں 40% boilerplate کوڈ کم کرتا ہے۔
ای میل اور پاس ورڈ فیلڈز، تصدیق اور لوڈنگ کی حالت کے ساتھ کلاسک لاگ ان اسکرین۔ ViewModel تین LiveData کا انتظام کرتا ہے: email، password اور loginResult۔
class LoginViewModel : ViewModel() {
private val _email = MutableLiveData("")
val email: LiveData<String> get() = _email
private val _password = MutableLiveData("")
val password: LiveData<String> get() = _password
private val _loginResult = MutableLiveData<Result<User>>()
val loginResult: LiveData<Result<User>> get() = _loginResult
fun onEmailChanged(text: String) {
_email.value = text
}
fun onPasswordChanged(text: String) {
_password.value = text
}
fun login() {
if (_email.value.isNullOrBlank() || _password.value.isNullOrBlank()) {
_loginResult.value = Result.failure(IllegalArgumentException("تمام فیلڈز بھریں"))
return
}
viewModelScope.launch {
try {
val user = authRepository.login(_email.value!!, _password.value!!)
_loginResult.value = Result.success(user)
} catch (e: Exception) {
_loginResult.value = Result.failure(e)
}
}
}
}
Room LiveData کو DAO استفسار کی واپسی کی قسم کے طور پر سپورٹ کرتا ہے: ٹیبل میں ہر تبدیلی پر LiveData خود بخود مبصرین کو مطلع کرتا ہے، جو reactice UI کے لیے مثالی ہے۔
@Dao
interface TaskDao {
@Query("SELECT * FROM tasks WHERE completed = 0")
fun getActiveTasks(): LiveData<List<Task>>
@Insert
suspend fun insertTask(task: Task)
}
// ViewModel میں:
class TaskViewModel(application: Application) : AndroidViewModel(application) {
private val dao = AppDatabase.getDatabase(application).taskDao()
val activeTasks: LiveData<List<Task>> = dao.getActiveTasks()
}
Room کوڈ تیار کرتا ہے جو tasks ٹیبل میں تبدیلیوں کو ٹریک کرتا ہے اور کسی بھی INSERT، UPDATE یا DELETE پر خود بخود LiveData کو اپ ڈیٹ کرتا ہے۔ یہ بغیر کسی اضافی کوڈ کے کام کرتا ہے — صرف @Query تشریح کے ساتھ LiveData واپسی کی قسم۔ IT Sectr میں ہم 2019 سے Android پروجیکٹس میں مقامی ڈیٹا کیشنگ کے لیے Room + LiveData کو معیاری اسٹیک کے طور پر استعمال کرتے ہیں۔
اکثر پوچھے گئے سوالات
LiveData — Lifecycle کی بلٹ ان سپورٹ کے ساتھ قابل مشاہدہ کنٹینر: Observer خود بخود فعال/غیر فعال ہوتا ہے۔ StateFlow — Kotlin Coroutines (Kotlinx Coroutines 1.3.7+) سے رد عمل کا سٹریم، Lifecycle سے منسلک نہیں، لیکن stateIn(WhileSubscribed) کے ذریعے اسے سپورٹ کرتا ہے۔ StateFlow کو View میں لائف سائیکل کے واضح انتظام کی ضرورت ہے، لیکن یہ کوروٹینز، Flow آپریٹرز اور ملٹی پلیٹ فارم تک رسائی دیتا ہے۔ Google نئے Kotlin پروجیکٹس کے لیے StateFlow کی سفارش کرتا ہے، جبکہ LiveData — Java کوڈ یا پرانی لائبریریوں کے ساتھ مطابقت کی ضرورت کے لیے۔
lifecycle-livedata-ktx لائبریری سے liveData.asFlow() extension-فنکشن استعمال کریں۔ یہ Flow بناتا ہے جو ہر تبدیلی پر LiveData کی موجودہ قدر کو خارج کرتا ہے۔ پھر .stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), initialValue) کے ذریعے StateFlow میں تبدیل کریں۔ الٹی تبدیلی — stateFlow.asLiveData()۔ باہمی تبدیلی ایک ہی پروجیکٹ میں دونوں لائبریریوں کے فوائد استعمال کرنے کی اجازت دیتی ہے۔
postValue() موخر قدر کو ذخیرہ کرنے کے لیے AtomicReference استعمال کرتا ہے۔ اگر postValue() مین تھریڈ کے ذریعے پروسیس ہونے سے پہلے دو بار کال کیا جائے تو پہلی قدر دوسری سے اوور رائٹ ہو جائے گی — Observable صرف آخری حاصل کرے گا۔ اس کی وجہ یہ ہے کہ LiveData میں اندرونی قطار نہیں ہے: یہ صرف ایک موخر قدر ذخیرہ کرتا ہے۔ ہر درمیانی نقطہ (1%, 2%, … 100%) منتقل کرنے کے لیے مین تھریڈ پر setValue() یا kotlinx-coroutines سے ConflatedFlow استعمال کریں۔
ہاں، LiveData کو observeForever() کے ذریعے دیکھا جا سکتا ہے، بغیر LifecycleOwner کے Observer پاس کر کے۔ تاہم، اس صورت میں ان سبسکرپشن واضح طور پر removeObserver() کے ذریعے ہونی چاہیے — خودکار ان سبسکرپشن کام نہیں کرتی۔ observeForever() سروسز، ContentProvider یا ViewModel میں استعمال ہوتا ہے جہاں LifecycleOwner دستیاب نہ ہو۔ Google کی سفارش کے مطابق، Activity/Fragment میں observeForever() سے پرہیز کریں — LifecycleOwner کے ساتھ observe() استعمال کریں۔
رویے کی خصوصیت: جب LiveData کو نیا فعال Observer ملتا ہے تو وہ فوری طور پر آخری قدر حاصل کرتا ہے (اگر سیٹ کی گئی ہو)۔ LiveData کے پرانے ورژن (lifecycle 2.5.0 سے پہلے) فعال حالت میں آنے پر غیر فعال سبسکرائبرز کو بھی قدر پہنچاتے تھے — یہ درست کر دیا گیا ہے۔ موجودہ ورژن میں LiveData غیر فعال سے فعال حالت میں آنے پر آخری قدر حاصل کرتا ہے، جو اسکرینوں کی ابتدا کو آسان بناتا ہے۔
خلاصہ
ہم ایک موبائل ایپلیکیشن ٹرنکی تیار کریں گے
IT Sectr 2017 سے اسٹارٹ اپس اور کاروبار کے لیے iOS اور Android ایپلیکیشنز بناتا ہے۔ ہم آپ کو مشورہ دیں گے اور بہترین حل تجویز کریں گے۔
مزید پڑھیں