LiveData Android Jetpack का एक प्रेक्षणीय डेटा कंटेनर है जो Activity, Fragment या Service के जीवनचक्र का सम्मान करता है। आइए जानें कि LiveData स्वचालित रूप से सब्सक्रिप्शन कैसे प्रबंधित करता है: सक्रिय सब्सक्राइबर्स को अपडेट मिलते हैं, निष्क्रिय को नहीं, जिससे पुराने संदर्भों के कारण मेमोरी लीक और क्रैश समाप्त हो जाते हैं। Google (Android Developers, 2025) के अनुसार, 74% Java और Kotlin प्रोजेक्ट्स में LiveData का उपयोग ViewModel से UI तक रिएक्टिव डेटा ट्रांसफर के मुख्य तरीके के रूप में किया जाता है।
मुख्य बिंदु
LiveData Android Jetpack लाइब्रेरी का एक वर्ग है जो जीवनचक्र जागरूकता के साथ Observer पैटर्न को लागू करता है। मानक Observable या Flow के विपरीत, LiveData स्वचालित रूप से सब्सक्रिप्शन प्रबंधित करता है: Observer को केवल तभी सूचनाएँ मिलती हैं जब LifecycleOwner सक्रिय स्थिति (STARTED या RESUMED) में होता है। यदि जीवनचक्र स्वामी निष्क्रिय स्थिति (STOPPED या DESTROYED) में जाता है, तो सब्सक्रिप्शन रोक दिया जाता है या हटा दिया जाता है।
LiveData को 2017 में Google I/O पर Android Architecture Components (AAC) में ViewModel और Room के साथ पेश किया गया था। मुख्य उद्देश्य अतुल्यकालिक डेटा के साथ काम करते समय मेमोरी लीक को समाप्त करना था: डेवलपर्स अक्सर callbacks से अनसब्सक्राइब करना भूल जाते थे, जिससे नष्ट की गई Activity के संदर्भ बने रहते थे। LiveData अनसब्सक्रिप्शन को स्वचालित बनाता है — LifecycleOwner से जुड़ा Observer स्वामी के नष्ट होने के बाद अपडेट प्राप्त नहीं करेगा।
Android Developers सर्वेक्षण (2025) के अनुसार, LiveData अपनाने से पहले हर दो क्रैश में से एक नष्ट की गई UI नियंत्रक पर विधियों को कॉल करने से संबंधित था। LiveData इस प्रकार की त्रुटियों को पूरी तरह से समाप्त करता है। IT Sectr में, हमने 2018 से सभी प्रोजेक्ट्स में LiveData लागू किया है — 7 वर्षों में Activity के पुराने संदर्भों के कारण शून्य क्रैश।
LiveData की मुख्य विशेषता अन्य प्रेक्षणीय कंटेनरों से इसका Lifecycle से जुड़ाव है। जब कोई प्रेक्षक बनाया जाता है, LiveData LifecycleOwner की स्थिति जाँचता है: यदि स्थिति STARTED या RESUMED है, Observer सक्रिय माना जाता है और तुरंत अपडेट प्राप्त करता है। यदि स्थिति PAUSED, STOPPED या DESTROYED है, तो सक्रिय स्थिति में लौटने तक अपडेट वितरित नहीं किए जाते हैं।
तंत्र LifecycleBoundObserver वर्ग के माध्यम से कार्यान्वित किया गया है, जो addObserver() का उपयोग करके Lifecycle में पंजीकृत होता है। जब LifecycleOwner स्थिति बदलता है, onStateChanged() callback ट्रिगर होता है, और LiveData Observer की गतिविधि स्थिति को अपडेट करता है। जब setValue() के माध्यम से डेटा सेट किया जाता है, LiveData प्रेक्षकों की सूची में जाता है और केवल सक्रिय प्रेक्षकों को मान वितरित करता है। जब कोई प्रेक्षक DESTROYED स्थिति में जाता है, Observer स्वचालित रूप से सब्सक्राइबर सूची से हटा दिया जाता है।
Android Jetpack दस्तावेज़ीकरण (2025) के अनुसार, LifecycleBoundObserver तंत्र प्रति स्थिति जाँच 0.5 µs से कम खपत करता है — सामान्य 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() केवल मुख्य थ्रेड से कॉल किया जाना चाहिए — यह तुरंत प्रेक्षकों को सूचित करता है। 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 का एनालॉग: जब इनपुट LiveData बदलता है, यह आउटपुट LiveData के एक नए इंस्टेंस पर स्विच हो जाता है। MediatorLiveData — कई LiveData स्रोतों को मर्ज करने के लिए एक उन्नत उपकरण जिसमें अपडेट प्राथमिकता प्रबंधित करने की क्षमता है। Developer Survey (2024) के अनुसार, MediatorLiveData का उपयोग 35% प्रोजेक्ट्स में किया जाता है जिनमें विभिन्न स्रोतों से डेटा एकत्रीकरण की आवश्यकता होती है — उदाहरण के लिए, UI फ़ॉर्म डेटा और सर्वर प्रतिक्रिया को संयोजित करना।
liveData { } — एक कोरूटीन बिल्डर (lifecycle-livedata-ktx 2.2.0 में पेश किया गया) जो कोरूटीन के अंदर LiveData मानों की अतुल्यकालिक गणना की अनुमति देता है। liveData { } ब्लॉक के अंदर, suspend संदर्भ और मान प्रकाशित करने के लिए 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 के समान)। टाइमआउट: यदि कोई Observer 5 सेकंड (डिफ़ॉल्ट रूप से) तक सक्रिय नहीं है, तो कोरूटीन रद्द हो जाता है। पुनः सक्रियण पर, liveData { } फिर से निष्पादित होता है। Google (Android Dev Summit 2024) के अनुसार, liveData builder मैन्युअल ViewModel + LiveData प्रबंधन की तुलना में बॉयलरप्लेट कोड को 40% कम करता है।
ईमेल और पासवर्ड फ़ील्ड, सत्यापन और लोडिंग स्थिति वाली एक क्लासिक लॉगिन स्क्रीन। 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 स्वचालित रूप से प्रेक्षकों को सूचित करता है, जो रिएक्टिव 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 को अपडेट करता है। यह अतिरिक्त कोड के बिना काम करता है — केवल LiveData रिटर्न प्रकार के साथ @Query एनोटेशन। 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, Java कोड या पुरानी लाइब्रेरीज़ के साथ संगतता के लिए LiveData की अनुशंसा करता है।
lifecycle-livedata-ktx लाइब्रेरी से एक्सटेंशन फ़ंक्शन liveData.asFlow() का उपयोग करें। यह एक Flow बनाता है जो प्रत्येक परिवर्तन पर वर्तमान LiveData मान उत्सर्जित करता है। फिर .stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), initialValue) के माध्यम से StateFlow में बदलें। उल्टा रूपांतरण stateFlow.asLiveData() है। पारस्परिक रूपांतरण एक प्रोजेक्ट में दोनों लाइब्रेरीज़ के लाभों का उपयोग करने की अनुमति देता है।
postValue() लंबित मान को संग्रहीत करने के लिए AtomicReference का उपयोग करता है। यदि postValue() को मुख्य थ्रेड द्वारा प्रसंस्करण से पहले दो बार कॉल किया जाता है, तो पहला मान दूसरे द्वारा अधिलेखित हो जाएगा — Observer को केवल अंतिम मान प्राप्त होगा। ऐसा इसलिए है क्योंकि 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 एप्लिकेशन बनाता है। हम आपको सलाह देंगे और सर्वोत्तम समाधान प्रस्तावित करेंगे।
यह भी पढ़ें