LiveData के बारे में खास जानकारी यह Android Jetpack का हिस्सा है.
LiveData
, डेटा होल्डर की ऐसी क्लास है जिसे ऑब्ज़र्व किया जा सकता है. सामान्य ऑब्ज़र्वेबल के मुकाबले, LiveData लाइफ़साइकल के बारे में जानकारी रखता है. इसका मतलब है कि यह ऐप्लिकेशन के अन्य कॉम्पोनेंट के लाइफ़साइकल का ध्यान रखता है. जैसे, ऐक्टिविटी, फ़्रैगमेंट या सेवाएं. इस जानकारी से यह पक्का होता है कि LiveData सिर्फ़ उन ऐप्लिकेशन कॉम्पोनेंट ऑब्ज़र्वर को अपडेट करता है जो लाइफ़साइकल की चालू स्थिति में हैं.
LiveData, किसी ऑब्ज़र्वर को चालू स्थिति में तब मानता है, जब उसका लाइफ़साइकल STARTED
या RESUMED
स्थिति में हो. ऑब्ज़र्वर को Observer
क्लास से दिखाया जाता है. LiveData सिर्फ़ उन ऑब्ज़र्वर को अपडेट की सूचना देता है जो ऐक्टिव हैं. LiveData
ऑब्जेक्ट देखने के लिए रजिस्टर किए गए, इनऐक्टिव ऑब्ज़र्वर को बदलावों के बारे में सूचना नहीं दी जाती.
LifecycleOwner
इंटरफ़ेस को लागू करने वाले ऑब्जेक्ट के साथ, ऑब्ज़र्वर को रजिस्टर किया जा सकता है. इस संबंध की मदद से, ऑब्ज़र्वर को तब हटाया जा सकता है, जब उससे जुड़े Lifecycle
ऑब्जेक्ट की स्थिति DESTROYED
में बदल जाए.
यह सुविधा खास तौर पर गतिविधियों और फ़्रैगमेंट के लिए मददगार होती है, क्योंकि वे LiveData
ऑब्जेक्ट को सुरक्षित तरीके से देख सकते हैं और उन्हें लीक होने की चिंता नहीं होती. गतिविधियों और फ़्रैगमेंट के लाइफ़साइकल खत्म होने पर, उनकी सदस्यता तुरंत रद्द कर दी जाती है.
LiveData का इस्तेमाल करने के तरीके के बारे में ज़्यादा जानने के लिए, LiveData ऑब्जेक्ट के साथ काम करना लेख पढ़ें.
LiveData का इस्तेमाल करने के फ़ायदे
LiveData का इस्तेमाल करने से ये फ़ायदे मिलते हैं:
- यह पक्का करना कि आपका यूज़र इंटरफ़ेस (यूआई), आपके डेटा की स्थिति से मेल खाता हो
- LiveData, ऑब्ज़र्वर पैटर्न का पालन करता है. डेटा में बदलाव होने पर, LiveData
Observer
ऑब्जेक्ट को सूचना देता है. इनObserver
ऑब्जेक्ट में यूज़र इंटरफ़ेस (यूआई) को अपडेट करने के लिए, अपने कोड को एक साथ जोड़ा जा सकता है. इस तरह, ऐप्लिकेशन का डेटा बदलने पर, आपको यूज़र इंटरफ़ेस (यूआई) को अपडेट करने की ज़रूरत नहीं पड़ती, क्योंकि ऑब्ज़र्वर आपके लिए यह काम करता है. - कोई मेमोरी लीक नहीं
- ऑब्जर्वर,
Lifecycle
ऑब्जेक्ट से जुड़े होते हैं. साथ ही, जब उनके लाइफ़साइकल को खत्म कर दिया जाता है, तो वे अपने-आप मिट जाते हैं. - बंद की गई गतिविधियों की वजह से क्रैश नहीं होना
- अगर ऑब्ज़र्वर का लाइफ़साइकल चालू नहीं है, जैसे कि बैक स्टैक में मौजूद किसी ऐक्टिविटी के मामले में, तो उसे कोई LiveData इवेंट नहीं मिलता.
- लाइफ़साइकल को मैन्युअल तरीके से मैनेज करने की ज़रूरत नहीं है
- यूज़र इंटरफ़ेस (यूआई) कॉम्पोनेंट सिर्फ़ काम के डेटा को देखते हैं और डेटा को देखना बंद या फिर से शुरू नहीं करते. LiveData, इन सभी बदलावों को अपने-आप मैनेज करता है. ऐसा इसलिए, क्योंकि यह लाइफ़साइकल के स्टेटस में होने वाले बदलावों को मॉनिटर करता है.
- हमेशा अप-टू-डेट डेटा
- अगर कोई लाइफ़साइकल इनऐक्टिव हो जाता है, तो फिर से चालू होने पर उसे नया डेटा मिलता है. उदाहरण के लिए, बैकग्राउंड में चल रही किसी गतिविधि को फ़ोरग्राउंड में वापस आने के तुरंत बाद, नया डेटा मिलता है.
- कॉन्फ़िगरेशन में सही बदलाव करना
- अगर कॉन्फ़िगरेशन में हुए बदलाव की वजह से, किसी ऐक्टिविटी या फ़्रैगमेंट को फिर से बनाया जाता है, तो उसे तुरंत उपलब्ध सबसे नया डेटा मिल जाता है. जैसे, डिवाइस के रोटेशन की वजह से.
- संसाधन शेयर करना
- सिस्टम सेवाओं को रैप करने के लिए, सिंगलटन पैटर्न का इस्तेमाल करके
LiveData
ऑब्जेक्ट को बड़ा किया जा सकता है, ताकि उन्हें आपके ऐप्लिकेशन में शेयर किया जा सके.LiveData
ऑब्जेक्ट, सिस्टम सेवा से एक बार कनेक्ट होता है. इसके बाद, रिसॉर्स की ज़रूरत वाले किसी भी ऑब्ज़र्वर को सिर्फ़LiveData
ऑब्जेक्ट को देखा जा सकता है. ज़्यादा जानकारी के लिए, LiveData का इस्तेमाल करना लेख पढ़ें.
LiveData ऑब्जेक्ट के साथ काम करना
LiveData
ऑब्जेक्ट के साथ काम करने के लिए, यह तरीका अपनाएं:
- किसी खास तरह का डेटा सेव करने के लिए,
LiveData
का इंस्टेंस बनाएं. आम तौर पर, ऐसा आपकीViewModel
क्लास में किया जाता है. Observer
ऑब्जेक्ट बनाएं, जोonChanged()
तरीका तय करता है. यह तरीका यह कंट्रोल करता है किLiveData
ऑब्जेक्ट के सेव किए गए डेटा में बदलाव होने पर क्या होगा. आम तौर पर, किसी यूज़र इंटरफ़ेस (यूआई) कंट्रोलर मेंObserver
ऑब्जेक्ट बनाया जाता है. जैसे, ऐक्टिविटी या फ़्रैगमेंट.observe()
तरीके का इस्तेमाल करके,Observer
ऑब्जेक्ट कोLiveData
ऑब्जेक्ट से अटैच करें.observe()
का तरीका,LifecycleOwner
ऑब्जेक्ट लेता है. इससेObserver
ऑब्जेक्ट,LiveData
ऑब्जेक्ट की सदस्यता ले लेता है, ताकि उसे बदलावों की सूचना मिल सके. आम तौर पर,Observer
ऑब्जेक्ट को किसी यूज़र इंटरफ़ेस (यूआई) कंट्रोलर में अटैच किया जाता है, जैसे कि ऐक्टिविटी या फ़्रैगमेंट.
LiveData
ऑब्जेक्ट में सेव की गई वैल्यू को अपडेट करने पर, यह सभी रजिस्टर किए गए ऑब्ज़र्वर को ट्रिगर करता है. ऐसा तब तक होता है, जब तक अटैच किया गया LifecycleOwner
चालू रहता है.
LiveData की मदद से, यूज़र इंटरफ़ेस (यूआई) कंट्रोलर के ऑब्ज़र्वर, अपडेट की सदस्यता ले सकते हैं. जब LiveData
ऑब्जेक्ट में मौजूद डेटा बदलता है, तो यूज़र इंटरफ़ेस (यूआई) अपने-आप अपडेट हो जाता है.
LiveData ऑब्जेक्ट बनाना
LiveData एक रैपर है, जिसका इस्तेमाल किसी भी डेटा के साथ किया जा सकता है. इसमें List
जैसे Collections
को लागू करने वाले ऑब्जेक्ट भी शामिल हैं. आम तौर पर, LiveData
ऑब्जेक्ट को ViewModel
ऑब्जेक्ट में सेव किया जाता है. साथ ही, इसे किसी गेट्टर तरीके से ऐक्सेस किया जाता है. इसका उदाहरण यहां दिया गया है:
Kotlin
class NameViewModel : ViewModel() { // Create a LiveData with a String val currentName: MutableLiveData<String> by lazy { MutableLiveData<String>() } // Rest of the ViewModel... }
Java
public class NameViewModel extends ViewModel { // Create a LiveData with a String private MutableLiveData<String> currentName; public MutableLiveData<String> getCurrentName() { if (currentName == null) { currentName = new MutableLiveData<String>(); } return currentName; } // Rest of the ViewModel... }
शुरुआत में, LiveData
ऑब्जेक्ट में डेटा सेट नहीं होता.
ViewModel
क्लास के फ़ायदों और इस्तेमाल के बारे में ज़्यादा जानने के लिए,
ViewModel गाइड पढ़ें.
LiveData ऑब्जेक्ट को ऑब्ज़र्व करना
ज़्यादातर मामलों में, किसी ऐप्लिकेशन कॉम्पोनेंट के onCreate()
तरीके से, LiveData
ऑब्जेक्ट को मॉनिटर करना शुरू करना सही होता है. ऐसा इन वजहों से किया जाता है:
- यह पक्का करने के लिए कि सिस्टम किसी ऐक्टिविटी या फ़्रैगमेंट के
onResume()
मैथड से ज़रूरत से ज़्यादा कॉल न करे. - यह पक्का करने के लिए कि ऐक्टिविटी या फ़्रैगमेंट में ऐसा डेटा हो जिसे चालू होने के तुरंत बाद दिखाया जा सके. जब कोई ऐप्लिकेशन कॉम्पोनेंट
STARTED
स्थिति में होता है, तो उसे उनLiveData
ऑब्जेक्ट से सबसे नई वैल्यू मिलती है जिनका वह निगरानी कर रहा है. ऐसा सिर्फ़ तब होता है, जब निगरानी के लिएLiveData
ऑब्जेक्ट को सेट किया गया हो.
आम तौर पर, LiveData सिर्फ़ तब अपडेट डिलीवर करता है, जब डेटा में बदलाव होता है. साथ ही, यह अपडेट सिर्फ़ सक्रिय ऑब्ज़र्वर को डिलीवर करता है. हालांकि, इस व्यवहार में एक अपवाद है. जब ऑब्ज़र्वर की स्थिति, इनऐक्टिव से ऐक्टिव में बदलती है, तब उन्हें भी अपडेट मिलता है. इसके अलावा, अगर ऑब्ज़र्वर की स्थिति दूसरी बार इनऐक्टिव से ऐक्टिव में बदलती है, तो उसे सिर्फ़ तब अपडेट मिलता है, जब पिछली बार ऐक्टिव होने के बाद से वैल्यू बदली हो.
यहां दिए गए सैंपल कोड में, LiveData
ऑब्जेक्ट को मॉनिटर करने का तरीका बताया गया है:
Kotlin
class NameActivity : AppCompatActivity() { // Use the 'by viewModels()' Kotlin property delegate // from the activity-ktx artifact private val model: NameViewModel by viewModels() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // Other code to setup the activity... // Create the observer which updates the UI. val nameObserver = Observer<String> { newName -> // Update the UI, in this case, a TextView. nameTextView.text = newName } // Observe the LiveData, passing in this activity as the LifecycleOwner and the observer. model.currentName.observe(this, nameObserver) } }
Java
public class NameActivity extends AppCompatActivity { private NameViewModel model; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Other code to setup the activity... // Get the ViewModel. model = new ViewModelProvider(this).get(NameViewModel.class); // Create the observer which updates the UI. final Observer<String> nameObserver = new Observer<String>() { @Override public void onChanged(@Nullable final String newName) { // Update the UI, in this case, a TextView. nameTextView.setText(newName); } }; // Observe the LiveData, passing in this activity as the LifecycleOwner and the observer. model.getCurrentName().observe(this, nameObserver); } }
nameObserver
को पैरामीटर के तौर पर पास करके, observe()
को कॉल करने के बाद, mCurrentName
में सेव की गई सबसे हाल की वैल्यू देने के लिए, onChanged()
को तुरंत लागू किया जाता है.
अगर LiveData
ऑब्जेक्ट ने mCurrentName
में कोई वैल्यू सेट नहीं की है, तो onChanged()
को कॉल नहीं किया जाता.
LiveData ऑब्जेक्ट अपडेट करना
LiveData में सेव किए गए डेटा को अपडेट करने का कोई सार्वजनिक तरीका नहीं है. MutableLiveData
क्लास, setValue(T)
और postValue(T)
तरीकों को सार्वजनिक तौर पर दिखाती है. अगर आपको LiveData
ऑब्जेक्ट में सेव की गई वैल्यू में बदलाव करना है, तो आपको इनका इस्तेमाल करना होगा. आम तौर पर, MutableLiveData
का इस्तेमाल ViewModel
में किया जाता है. इसके बाद, ViewModel
ऑब्ज़र्वर को सिर्फ़ ऐसे LiveData
ऑब्जेक्ट दिखाता है जिन्हें बदला नहीं जा सकता.
ऑब्ज़र्वर रिलेशनशिप सेट अप करने के बाद, LiveData
ऑब्जेक्ट की वैल्यू को अपडेट किया जा सकता है. इस बारे में नीचे दिए गए उदाहरण में बताया गया है. इसमें, उपयोगकर्ता के किसी बटन पर टैप करने पर, सभी ऑब्ज़र्वर ट्रिगर होते हैं:
Kotlin
button.setOnClickListener { val anotherName = "John Doe" model.currentName.setValue(anotherName) }
Java
button.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { String anotherName = "John Doe"; model.getCurrentName().setValue(anotherName); } });
उदाहरण में setValue(T)
को कॉल करने पर, ऑब्ज़र्वर John Doe
वैल्यू के साथ अपने onChanged()
तरीकों को कॉल करते हैं. उदाहरण में बटन दबाने की जानकारी दी गई है, लेकिन mName
को अपडेट करने के लिए setValue()
या postValue()
को कई वजहों से कॉल किया जा सकता है. जैसे, नेटवर्क अनुरोध या डेटाबेस लोड होने के बाद. सभी मामलों में, setValue()
या postValue()
को कॉल करने पर, ऑब्ज़र्वर ट्रिगर होते हैं और यूज़र इंटरफ़ेस (यूआई) अपडेट होता है.
Room के साथ LiveData का इस्तेमाल करना
Room परसिस्टेंस लाइब्रेरी, ऑब्ज़र्व की जा सकने वाली क्वेरी के साथ काम करती है. ये क्वेरी, LiveData
ऑब्जेक्ट दिखाती हैं.
ऑब्ज़र्वेबल क्वेरी, डेटाबेस ऐक्सेस ऑब्जेक्ट (डीएओ) के हिस्से के तौर पर लिखी जाती हैं.
डेटाबेस अपडेट होने पर, Room LiveData
ऑब्जेक्ट को अपडेट करने के लिए ज़रूरी कोड जनरेट करता है. जनरेट किया गया कोड, ज़रूरत पड़ने पर बैकग्राउंड थ्रेड पर एसिंक्रोनस तरीके से क्वेरी चलाता है. यह पैटर्न, यूज़र इंटरफ़ेस (यूआई) में दिखाए गए डेटा को डेटाबेस में सेव किए गए डेटा के साथ सिंक रखने के लिए मददगार होता है. रूम परसिस्टेंट लाइब्रेरी की गाइड में, Room और डीएओ के बारे में ज़्यादा पढ़ा जा सकता है.
LiveData के साथ कोरूटीन का इस्तेमाल करना
LiveData
में Kotlin कोरूटीन के लिए सहायता शामिल है. ज़्यादा जानकारी के लिए, Android आर्किटेक्चर कॉम्पोनेंट के साथ Kotlin कोरूटीन इस्तेमाल करना लेख पढ़ें.
ऐप्लिकेशन के आर्किटेक्चर में LiveData
LiveData
, लाइफ़साइकल की जानकारी रखता है. यह ऐक्टिविटी और फ़्रैगमेंट जैसी इकाइयों की लाइफ़साइकल को फ़ॉलो करता है. लाइफ़साइकल के मालिकों और ViewModel
ऑब्जेक्ट जैसे अन्य ऑब्जेक्ट के बीच कम्यूनिकेट करने के लिए, LiveData
का इस्तेमाल करें.
ViewModel
की मुख्य ज़िम्मेदारी, यूज़र इंटरफ़ेस (यूआई) से जुड़े डेटा को लोड और मैनेज करना है. इस वजह से, यह LiveData
ऑब्जेक्ट को होल्ड करने के लिए एक बेहतरीन विकल्प है. ViewModel
में LiveData
ऑब्जेक्ट बनाएं और उनका इस्तेमाल करके, यूज़र इंटरफ़ेस (यूआई) लेयर में स्टेटस दिखाएं.
गतिविधियों और फ़्रैगमेंट में LiveData
इंस्टेंस नहीं होने चाहिए, क्योंकि उनकी भूमिका डेटा दिखाने की है, न कि स्थिति दिखाने की. साथ ही, ऐक्टिविटी और फ़्रैगमेंट में डेटा सेव न करने से, यूनिट टेस्ट लिखना आसान हो जाता है.
ऐसा हो सकता है कि आपको अपनी डेटा लेयर क्लास में LiveData
ऑब्जेक्ट इस्तेमाल करने का मन करे, लेकिन LiveData
को डेटा की असाइनोक्रोनस स्ट्रीम को हैंडल करने के लिए डिज़ाइन नहीं किया गया है. हालांकि, ऐसा करने के लिए LiveData
ट्रांसफ़ॉर्मेशन और MediatorLiveData
का इस्तेमाल किया जा सकता है, लेकिन इस तरीके में कुछ समस्याएं हैं: डेटा स्ट्रीम को आपस में जोड़ने की सुविधा काफ़ी सीमित है. साथ ही, सभी LiveData
ऑब्जेक्ट (इनमें ट्रांसफ़ॉर्मेशन की मदद से बनाए गए ऑब्जेक्ट भी शामिल हैं) को मुख्य थ्रेड पर देखा जाता है. नीचे दिए गए कोड में बताया गया है कि Repository
में LiveData
को होल्ड करने से मुख्य थ्रेड कैसे ब्लॉक हो सकता है:
Kotlin
class UserRepository { // DON'T DO THIS! LiveData objects should not live in the repository. fun getUsers(): LiveData<List<User>> { ... } fun getNewPremiumUsers(): LiveData<List<User>> { return getUsers().map { users -> // This is an expensive call being made on the main thread and may // cause noticeable jank in the UI! users .filter { user -> user.isPremium } .filter { user -> val lastSyncedTime = dao.getLastSyncedTime() user.timeCreated > lastSyncedTime } } }
Java
class UserRepository { // DON'T DO THIS! LiveData objects should not live in the repository. LiveData<List<User>> getUsers() { ... } LiveData<List<User>> getNewPremiumUsers() { return Transformations.map(getUsers(), // This is an expensive call being made on the main thread and may cause // noticeable jank in the UI! users -> users.stream() .filter(User::isPremium) .filter(user -> user.getTimeCreated() > dao.getLastSyncedTime()) .collect(Collectors.toList())); } }
अगर आपको अपने ऐप्लिकेशन की अन्य लेयर में डेटा स्ट्रीम का इस्तेमाल करना है, तो Kotlin फ़्लो का इस्तेमाल करें. इसके बाद, asLiveData()
का इस्तेमाल करके, उन्हें ViewModel
में LiveData
में बदलें.
इस कोडलैब में, Kotlin Flow
को LiveData
के साथ इस्तेमाल करने के बारे में ज़्यादा जानें.
Java से बनाए गए कोडबेस के लिए, कॉलबैक या RxJava
के साथ एग्ज़ीक्यूटर का इस्तेमाल करें.
LiveData का इस्तेमाल करना
LiveData, किसी ऑब्ज़र्वर को तब चालू स्थिति में मानता है, जब उसका लाइफ़साइकल STARTED
या RESUMED
स्टेटस में हो. यहां दिए गए सैंपल कोड में, LiveData
क्लास को एक्सटेंड करने का तरीका बताया गया है:
Kotlin
class StockLiveData(symbol: String) : LiveData<BigDecimal>() { private val stockManager = StockManager(symbol) private val listener = { price: BigDecimal -> value = price } override fun onActive() { stockManager.requestPriceUpdates(listener) } override fun onInactive() { stockManager.removeUpdates(listener) } }
Java
public class StockLiveData extends LiveData<BigDecimal> { private StockManager stockManager; private SimplePriceListener listener = new SimplePriceListener() { @Override public void onPriceChanged(BigDecimal price) { setValue(price); } }; public StockLiveData(String symbol) { stockManager = new StockManager(symbol); } @Override protected void onActive() { stockManager.requestPriceUpdates(listener); } @Override protected void onInactive() { stockManager.removeUpdates(listener); } }
इस उदाहरण में, कीमत सुनने वाले को लागू करने के लिए ये अहम तरीके शामिल हैं:
onActive()
मेथड को तब कॉल किया जाता है, जबLiveData
ऑब्जेक्ट में कोई ऐक्टिव ऑब्ज़र्वर हो. इसका मतलब है कि आपको इस तरीके से स्टॉक की कीमत में होने वाले अपडेट देखने होंगे.onInactive()
विधि को तब कॉल किया जाता है, जबLiveData
ऑब्जेक्ट में कोई ऐक्टिव ऑब्ज़र्वर न हो. कोई भी ऑब्ज़र्वर सुन नहीं रहा है, इसलिएStockManager
सेवा से कनेक्ट रहने की कोई ज़रूरत नहीं है.setValue(T)
तरीका,LiveData
इंस्टेंस की वैल्यू अपडेट करता है और बदलाव के बारे में सभी ऐक्टिव ऑब्ज़र्वर को सूचना देता है.
StockLiveData
क्लास का इस्तेमाल इस तरह किया जा सकता है:
Kotlin
public class MyFragment : Fragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) val myPriceListener: LiveData<BigDecimal> = ... myPriceListener.observe(viewLifecycleOwner, Observer<BigDecimal> { price: BigDecimal? -> // Update the UI. }) } }
Java
public class MyFragment extends Fragment { @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); LiveData<BigDecimal> myPriceListener = ...; myPriceListener.observe(getViewLifecycleOwner(), price -> { // Update the UI. }); } }
observe()
तरीका, फ़्रैगमेंट के व्यू से जुड़े LifecycleOwner
को पहले आर्ग्युमेंट के तौर पर पास करता है. ऐसा करने से पता चलता है कि यह ऑब्ज़र्वर, मालिक से जुड़े Lifecycle
ऑब्जेक्ट से जुड़ा है. इसका मतलब है कि:
- अगर
Lifecycle
ऑब्जेक्ट चालू स्थिति में नहीं है, तो वैल्यू बदलने पर भी ऑब्ज़र्वर को कॉल नहीं किया जाता. Lifecycle
ऑब्जेक्ट के खत्म होने के बाद, ऑब्ज़र्वर अपने-आप हट जाता है.
LiveData
ऑब्जेक्ट, लाइफ़साइकल के बारे में जानते हैं. इसका मतलब है कि इन्हें कई गतिविधियों, फ़्रैगमेंट, और सेवाओं के बीच शेयर किया जा सकता है. उदाहरण को आसान बनाए रखने के लिए, LiveData
क्लास को सिंगलटन के तौर पर इस तरह लागू किया जा सकता है:
Kotlin
class StockLiveData(symbol: String) : LiveData<BigDecimal>() { private val stockManager: StockManager = StockManager(symbol) private val listener = { price: BigDecimal -> value = price } override fun onActive() { stockManager.requestPriceUpdates(listener) } override fun onInactive() { stockManager.removeUpdates(listener) } companion object { private lateinit var sInstance: StockLiveData @MainThread fun get(symbol: String): StockLiveData { sInstance = if (::sInstance.isInitialized) sInstance else StockLiveData(symbol) return sInstance } } }
Java
public class StockLiveData extends LiveData<BigDecimal> { private static StockLiveData sInstance; private StockManager stockManager; private SimplePriceListener listener = new SimplePriceListener() { @Override public void onPriceChanged(BigDecimal price) { setValue(price); } }; @MainThread public static StockLiveData get(String symbol) { if (sInstance == null) { sInstance = new StockLiveData(symbol); } return sInstance; } private StockLiveData(String symbol) { stockManager = new StockManager(symbol); } @Override protected void onActive() { stockManager.requestPriceUpdates(listener); } @Override protected void onInactive() { stockManager.removeUpdates(listener); } }
इसका इस्तेमाल फ़्रैगमेंट में इस तरह किया जा सकता है:
Kotlin
class MyFragment : Fragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) StockLiveData.get(symbol).observe(viewLifecycleOwner, Observer<BigDecimal> { price: BigDecimal? -> // Update the UI. }) }
Java
public class MyFragment extends Fragment { @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); StockLiveData.get(symbol).observe(getViewLifecycleOwner(), price -> { // Update the UI. }); } }
एक से ज़्यादा फ़्रैगमेंट और गतिविधियां, MyPriceListener
इंस्टेंस को ऑब्ज़र्व कर सकती हैं.
LiveData, सिस्टम सेवा से सिर्फ़ तब कनेक्ट होता है, जब उनमें से एक या उससे ज़्यादा सेवाएं दिख रही हों और चालू हों.
LiveData में बदलाव करना
LiveData
ऑब्जेक्ट को ऑब्ज़र्वर के पास भेजने से पहले, उसमें सेव वैल्यू में बदलाव करें. इसके अलावा, किसी अन्य की वैल्यू के आधार पर दूसरा LiveData
इंस्टेंस भी दिया जा सकता है. Lifecycle
पैकेज, Transformations
क्लास उपलब्ध कराता है. इसमें ऐसे हेल्पर मेथड शामिल होते हैं जो इन स्थितियों में काम करते हैं.
Transformations.map()
LiveData
ऑब्जेक्ट में सेव की गई वैल्यू पर कोई फ़ंक्शन लागू करता है और नतीजे को डाउनस्ट्रीम पर भेजता है.
Kotlin
val userLiveData: LiveData<User> = UserLiveData() val userName: LiveData<String> = userLiveData.map { user -> "${user.name} ${user.lastName}" }
Java
LiveData<User> userLiveData = ...; LiveData<String> userName = Transformations.map(userLiveData, user -> { user.name + " " + user.lastName });
Transformations.switchMap()
map()
की तरह ही, यह फ़ंक्शनLiveData
ऑब्जेक्ट में सेव की गई वैल्यू पर लागू होता है. साथ ही, नतीजे को अनरैप करके डाउनस्ट्रीम पर भेजता है.switchMap()
में पास किए गए फ़ंक्शन सेLiveData
ऑब्जेक्ट दिखना चाहिए, जैसा कि इस उदाहरण में दिखाया गया है:
Kotlin
private fun getUser(id: String): LiveData<User> { ... } val userId: LiveData<String> = ... val user = userId.switchMap { id -> getUser(id) }
Java
private LiveData<User> getUser(String id) { ...; } LiveData<String> userId = ...; LiveData<User> user = Transformations.switchMap(userId, id -> getUser(id) );
ऑब्ज़र्वर के लाइफ़साइकल में जानकारी को ले जाने के लिए, ट्रांसफ़ॉर्मेशन के तरीकों का इस्तेमाल किया जा सकता है. बदलावों का हिसाब तब तक नहीं लगाया जाता, जब तक कोई ऑब्ज़र्वर, मिले LiveData
ऑब्जेक्ट को देख रहा हो. ट्रांसफ़ॉर्मेशन का हिसाब, धीरे-धीरे लगाया जाता है. इसलिए, लाइफ़साइकल से जुड़ा व्यवहार, साफ़ तौर पर कॉल या डिपेंडेंसी के बिना, अपने-आप पास किया जाता है.
अगर आपको लगता है कि आपको ViewModel
ऑब्जेक्ट के अंदर Lifecycle
ऑब्जेक्ट की ज़रूरत है, तो ट्रांसफ़ॉर्मेशन एक बेहतर समाधान हो सकता है. उदाहरण के लिए, मान लें कि आपके पास एक यूज़र इंटरफ़ेस (यूआई) कॉम्पोनेंट है, जो कोई पता स्वीकार करता है और उस पते का पिन कोड दिखाता है. इस कॉम्पोनेंट के लिए, नॉन-एलिमेंट ViewModel
को लागू किया जा सकता है, जैसा कि यहां दिए गए सैंपल कोड में दिखाया गया है:
Kotlin
class MyViewModel(private val repository: PostalCodeRepository) : ViewModel() { private fun getPostalCode(address: String): LiveData<String> { // DON'T DO THIS return repository.getPostCode(address) } }
Java
class MyViewModel extends ViewModel { private final PostalCodeRepository repository; public MyViewModel(PostalCodeRepository repository) { this.repository = repository; } private LiveData<String> getPostalCode(String address) { // DON'T DO THIS return repository.getPostCode(address); } }
इसके बाद, यूज़र इंटरफ़ेस (यूआई) कॉम्पोनेंट को पिछले LiveData
ऑब्जेक्ट से अनरजिस्टर करना होगा और हर बार getPostalCode()
को कॉल करने पर, नए इंस्टेंस पर रजिस्टर करना होगा. इसके अलावा, अगर यूज़र इंटरफ़ेस (यूआई) कॉम्पोनेंट को फिर से बनाया जाता है, तो यह पिछले कॉल के नतीजे का इस्तेमाल करने के बजाय, repository.getPostCode()
तरीके के लिए एक और कॉल ट्रिगर करता है.
इसके बजाय, पिन कोड लुकअप को पते के इनपुट के ट्रांसफ़ॉर्मेशन के तौर पर लागू किया जा सकता है, जैसा कि नीचे दिए गए उदाहरण में दिखाया गया है:
Kotlin
class MyViewModel(private val repository: PostalCodeRepository) : ViewModel() { private val addressInput = MutableLiveData<String>() val postalCode: LiveData<String> = addressInput.switchMap { address -> repository.getPostCode(address) } private fun setInput(address: String) { addressInput.value = address } }
Java
class MyViewModel extends ViewModel { private final PostalCodeRepository repository; private final MutableLiveData<String> addressInput = new MutableLiveData(); public final LiveData<String> postalCode = Transformations.switchMap(addressInput, (address) -> { return repository.getPostCode(address); }); public MyViewModel(PostalCodeRepository repository) { this.repository = repository } private void setInput(String address) { addressInput.setValue(address); } }
इस मामले में, postalCode
फ़ील्ड को addressInput
के ट्रांसफ़ॉर्मेशन के तौर पर परिभाषित किया गया है. जब तक आपके ऐप्लिकेशन में postalCode
फ़ील्ड से जुड़ा कोई ऐक्टिव ऑब्ज़र्वर है, तब तक addressInput
में बदलाव होने पर, फ़ील्ड की वैल्यू फिर से कैलकुलेट की जाती है और उसे वापस लाया जाता है.
इस तरीके से, ऐप्लिकेशन के निचले लेवल पर LiveData
ऑब्जेक्ट बनाए जा सकते हैं. इनका हिसाब, मांग के हिसाब से लगाया जाता है. ViewModel
ऑब्जेक्ट, LiveData
ऑब्जेक्ट के रेफ़रंस आसानी से पा सकता है. इसके बाद, उन पर ट्रांसफ़ॉर्मेशन के नियम तय कर सकता है.
नए ट्रांसफ़ॉर्मेशन बनाना
आपके ऐप्लिकेशन में, 12 अलग-अलग ट्रांसफ़ॉर्मेशन फ़ंक्शन काम के हो सकते हैं. हालांकि, ये डिफ़ॉल्ट रूप से उपलब्ध नहीं होते. अपने हिसाब से बदलाव करने के लिए, MediatorLiveData
क्लास का इस्तेमाल किया जा सकता है. यह क्लास, दूसरे LiveData
ऑब्जेक्ट को सुनती है और उनसे मिलने वाले इवेंट को प्रोसेस करती है. MediatorLiveData
, सोर्स LiveData
ऑब्जेक्ट में अपनी स्थिति को सही तरीके से भेजता है. इस पैटर्न के बारे में ज़्यादा जानने के लिए, Transformations
क्लास का रेफ़रंस दस्तावेज़ देखें.
एक से ज़्यादा LiveData सोर्स को मर्ज करना
MediatorLiveData
, LiveData
का एक सबक्लास है. इसकी मदद से, एक से ज़्यादा LiveData सोर्स को मर्ज किया जा सकता है. जब भी किसी ओरिजनल LiveData सोर्स ऑब्जेक्ट में बदलाव होता है, तो MediatorLiveData
ऑब्जेक्ट के ऑब्ज़र्वर ट्रिगर हो जाते हैं.
उदाहरण के लिए, अगर आपके यूज़र इंटरफ़ेस (यूआई) में कोई ऐसा LiveData
ऑब्जेक्ट है जिसे किसी स्थानीय डेटाबेस या नेटवर्क से अपडेट किया जा सकता है, तो MediatorLiveData
ऑब्जेक्ट में ये सोर्स जोड़े जा सकते हैं:
- डेटाबेस में सेव किए गए डेटा से जुड़ा
LiveData
ऑब्जेक्ट. - नेटवर्क से ऐक्सेस किए गए डेटा से जुड़ा
LiveData
ऑब्जेक्ट.
दोनों सोर्स से अपडेट पाने के लिए, आपकी गतिविधि को सिर्फ़ MediatorLiveData
ऑब्जेक्ट को मॉनिटर करना होगा. ज़्यादा जानकारी के लिए, ऐप्लिकेशन के आर्किटेक्चर से जुड़ी गाइड में अतिरिक्त जानकारी: नेटवर्क की स्थिति दिखाना सेक्शन देखें.
अन्य संसाधन
LiveData
क्लास के बारे में ज़्यादा जानने के लिए, यहां दिए गए रिसॉर्स देखें.
सैंपल
- Sunflower, एक डेमो ऐप्लिकेशन है. इसमें, आर्किटेक्चर कॉम्पोनेंट के साथ काम करने के सबसे सही तरीके दिखाए गए हैं
कोडलैब
- Android Room with a View (Java) (Kotlin)
- Kotlin Flow और LiveData की मदद से, बेहतर कोरूटीन के बारे में जानें
ब्लॉग
- ViewModels और LiveData: पैटर्न + एंटीपैटर्न
- ViewModel के अलावा LiveData — बदलाव और MediatorLiveData का इस्तेमाल करके रिऐक्टिव पैटर्न
- स्नैकबार, नेविगेशन, और अन्य इवेंट के साथ LiveData (SingleLiveEvent का उदाहरण)
वीडियो
आपके लिए सुझाव
- ध्यान दें: JavaScript बंद होने पर लिंक टेक्स्ट दिखता है
- लाइफ़साइकल की जानकारी वाले कॉम्पोनेंट के साथ Kotlin कोरूटीन का इस्तेमाल करना
- लाइफ़साइकल की जानकारी वाले कॉम्पोनेंट की मदद से लाइफ़साइकल मैनेज करना
- पेजिंग लागू करने की जांच करना