Android MVVM ViewModel में संदर्भ कैसे प्राप्त करें


96

मैं अपने एंड्रॉइड ऐप में MVVM पैटर्न को लागू करने की कोशिश कर रहा हूं। मैंने पढ़ा है कि ViewModels में कोई एंड्रॉइड विशिष्ट कोड नहीं होना चाहिए (परीक्षण को आसान बनाने के लिए), हालांकि मुझे विभिन्न चीजों के लिए संदर्भ का उपयोग करने की आवश्यकता है (xml से संसाधन प्राप्त करना, वरीयताएँ शुरू करना, आदि)। इसे करने का बेहतरीन तरीका क्या है? मैंने देखा कि AndroidViewModelआवेदन के संदर्भ में एक संदर्भ है, हालांकि इसमें एंड्रॉइड विशिष्ट कोड है, इसलिए मुझे यकीन नहीं है कि अगर यह ViewModel में होना चाहिए। इसके अलावा जो लोग गतिविधि जीवन चक्र की घटनाओं में बंध जाते हैं, लेकिन मैं घटकों के दायरे का प्रबंधन करने के लिए डैगर का उपयोग कर रहा हूं, इसलिए मुझे यकीन नहीं है कि यह कैसे प्रभावित करेगा। मैं MVVM पैटर्न और डैगर के लिए नया हूँ इसलिए किसी भी मदद की सराहना की है!


बस अगर कोई उपयोग करने की कोशिश कर रहा है, AndroidViewModelलेकिन Cannot create instance exceptionतब आप मेरे इस जवाब का उल्लेख कर सकते हैं stackoverflow.com/a/62626408/1055241
gprathour

आपको एक ViewModel में संदर्भ का उपयोग नहीं करना चाहिए, इस तरह से संदर्भ प्राप्त करने के बजाय एक UseCase बनाएं
ढलाईकार

जवाबों:


79

आप एक Applicationसंदर्भ का उपयोग कर सकते हैं, जो आपको प्रदान करता है AndroidViewModel, आपको विस्तार करना चाहिए AndroidViewModelजो कि बस एक संदर्भ ViewModelशामिल है Application


एक जादू की तरह काम किया!
एसपीएम

64

Android आर्किटेक्चर घटकों के लिए मॉडल देखें,

अपनी गतिविधि के संदर्भ में गतिविधि के दृश्यमॉडल को स्मृति रिसाव के रूप में पारित करना एक अच्छा अभ्यास नहीं है।

इसलिए अपने ViewModel में संदर्भ प्राप्त करने के लिए, ViewModel वर्ग को Android View Model Class का विस्तार करना चाहिए । इस तरह आप संदर्भ को नीचे दिए गए उदाहरण कोड में दिखा सकते हैं।

class ActivityViewModel(application: Application) : AndroidViewModel(application) {

    private val context = getApplication<Application>().applicationContext

    //... ViewModel methods 

}

3
सीधे आवेदन पैरामीटर और एक सामान्य ViewModel का उपयोग क्यों नहीं करें? मुझे "getApplication <Application> ()" में कोई मतलब नहीं दिखता। यह सिर्फ बॉयलरप्लेट जोड़ता है।
9 जनवरी को अविश्वसनीय जन

यह स्मृति रिसाव क्यों होगा?
बेन बटरवर्थ

ओह, मैं देख रहा हूं, क्योंकि एक गतिविधि उसके दृश्य मॉडल (जैसे कि स्क्रीन के घूमने पर) से अधिक बार नष्ट हो जाएगी। दुर्भाग्य से, मेमोरी को कचरा संग्रह द्वारा जारी नहीं किया जाएगा क्योंकि दृश्य मॉडल में अभी भी इसका संदर्भ है।
बेन बटरवर्थ

52

ऐसा नहीं है कि ViewModels में परीक्षण को आसान बनाने के लिए Android विशिष्ट कोड नहीं होना चाहिए, क्योंकि यह अमूर्त है जो परीक्षण को आसान बनाता है।

ViewModels के संदर्भ में संदर्भ या दृश्य या अन्य वस्तुओं की तरह कुछ भी शामिल नहीं होना चाहिए, क्योंकि यह एक अलग जीवनचक्र है क्योंकि इसमें गतिविधियाँ और फ़्रैगमेंट की तुलना में अलग जीवन चक्र है।

इसका क्या मतलब है, आइए बताते हैं कि आप अपने ऐप पर एक रोटेशन परिवर्तन करते हैं। यह आपकी एक्टिविटी और फ्रैगमेंट को नष्ट करने का कारण बनता है इसलिए यह खुद को फिर से बनाता है। ViewModel इस स्थिति के दौरान बने रहने के लिए है, इसलिए यदि यह अभी भी नष्ट गतिविधि के लिए एक दृश्य या संदर्भ को पकड़े हुए है, तो क्रैश और अन्य अपवाद होने की संभावना है।

जैसा कि आप जो करना चाहते हैं वह आपको कैसे करना चाहिए, MVVM और ViewModel जेटबैक के डेटाबाइंडिंग घटक के साथ वास्तव में अच्छी तरह से काम करता है। ज्यादातर चीजों के लिए आप आम तौर पर एक स्ट्रिंग, इंट, या आदि के लिए स्टोर करेंगे, आप इसे सीधे प्रदर्शित करने के लिए डेटाबाइंडिंग का उपयोग कर सकते हैं, इस प्रकार ViewModel के अंदर मूल्य को स्टोर करने की आवश्यकता नहीं है।

लेकिन अगर आप डाटाबाइंडिंग नहीं चाहते हैं, तो आप अभी भी कंस्ट्रक्टर के अंदर कॉन्सेप्ट को पास कर सकते हैं या संसाधन तक पहुंचने के तरीके। बस अपने ViewModel के अंदर उस संदर्भ का एक उदाहरण न रखें।


1
यह मेरी समझ थी कि चलाने के लिए एंड्रॉइड-विशिष्ट कोड आवश्यक इंस्ट्रूमेंटेशन टेस्ट शामिल हैं, जो सादे JUnit परीक्षणों की तुलना में बहुत धीमा है। मैं वर्तमान में क्लिक तरीकों के लिए डेटाबाइंडिंग का उपयोग कर रहा हूं, लेकिन मैं यह नहीं देखता कि यह xml से संसाधन प्राप्त करने में या प्राथमिकताओं के लिए कैसे मदद करेगा। मुझे बस एहसास हुआ कि वरीयताओं के लिए, मुझे अपने मॉडल के अंदर भी एक संदर्भ की आवश्यकता होगी। वर्तमान में मैं क्या कर रहा हूं डैगर एप्लिकेशन संदर्भ को इंजेक्ट कर रहा है (संदर्भ मॉड्यूल इसे एप्लिकेशन क्लास के अंदर एक स्थिर विधि से प्राप्त करता है)
विंसेंट विलियम्स

@VincentWilliams हाँ, एक ViewModel का उपयोग करने से आपके यूआई घटकों से दूर आपके कोड को अमूर्त करने में मदद मिलती है, जिससे परीक्षण करना आपके लिए आसान हो जाता है। लेकिन, मैं जो कह रहा हूं, वह यह है कि किसी भी संदर्भ, दृश्य या पसंद को शामिल नहीं करने का प्राथमिक कारण परीक्षण कारणों से नहीं है, बल्कि व्यूमॉडल के जीवनचक्र के कारण है जो आपको क्रैश और अन्य त्रुटियों से बचने में मदद कर सकता है। डेटाबाइंडिंग के लिए, यह आपको संसाधनों के साथ मदद कर सकता है क्योंकि कोड में संसाधनों का उपयोग करने के लिए अधिकांश समय आपके स्ट्रिंग में, उस रंग, रंग को लागू करने की आवश्यकता के कारण होता है, जिसे डेटाबाइंडिंग सीधे कर सकती है।
जैकी

3
अगर मैं एक टेक्स्ट फॉर्म में टेक्स्ट को टॉगल करना चाहता हूं, जो वैल्यू फॉर्म व्यूमोडेल पर आधारित है, तो स्ट्रिंग को स्थानीयकृत करने की आवश्यकता है, इसलिए मुझे अपने व्यूमॉडल में संसाधन प्राप्त करने की आवश्यकता है, बिना संदर्भ के मैं संसाधनों का उपयोग कैसे करूंगा?
सृष्टि रॉय

3
@SrtitiRoy यदि आप डेटाबाइंडिंग का उपयोग करते हैं, तो आपके व्यूमॉडल के मूल्य के आधार पर टेक्स्ट व्यू के पाठ को टॉगल करना आसानी से संभव है। आपके ViewModel के अंदर एक प्रसंग तक पहुँचने की कोई आवश्यकता नहीं है क्योंकि यह सब लेआउट फ़ाइलों के भीतर होता है। हालाँकि, यदि आपको अपने ViewModel के भीतर एक संदर्भ का उपयोग करना चाहिए, तो आपको ViewModel के बजाय AndroidViewModel का उपयोग करने पर विचार करना चाहिए। AndroidViewModel में एप्लिकेशन संदर्भ शामिल है जिसे आप getApplication () के साथ कॉल कर सकते हैं, ताकि यदि आपके ViewModel को एक संदर्भ की आवश्यकता हो तो अपनी संदर्भ आवश्यकताओं को पूरा करें।
जैकी

1
@Pacerier आपने ViewModel के मुख्य उद्देश्य को गलत समझा है। यह चिंताओं के मुद्दे से अलग है। ViewModel को किसी भी दृश्य के संदर्भ नहीं रखना चाहिए, क्योंकि यह जिम्मेदारी है कि दृश्य परत द्वारा प्रदर्शित किए जा रहे डेटा को बनाए रखना है। UI घटक, उर्फ़ दृश्य, दृश्य परत द्वारा बनाए रखा जाता है और यदि आवश्यक हो तो Android सिस्टम दृश्य को फिर से बनाएगा। पुराने दृश्यों का संदर्भ रखते हुए इस व्यवहार के साथ संघर्ष करेंगे और मेमोरी लीक का कारण बनेंगे।
जैकी

16

संक्षिप्त उत्तर - ऐसा न करें

क्यों ?

यह देखने के मॉडल के पूरे उद्देश्य को हरा देता है

लगभग सभी चीजें जो आप मॉडल में देख सकते हैं, लाइवडैटा इंस्टेंस और विभिन्न अन्य अनुशंसित दृष्टिकोणों का उपयोग करके गतिविधि / टुकड़े में किया जा सकता है।


26
तब AndroidViewModel वर्ग भी क्यों मौजूद है?
एलेक्स बर्डनिकोव

1
@AlexBerdnikov MVVM का उद्देश्य ViewModel से दृश्य (गतिविधि / टुकड़ा) को MVP से भी अधिक अलग करना है। ताकि टेस्ट करना आसान हो जाए।
hushed_voice

3
@free_style स्पष्टीकरण के लिए धन्यवाद, लेकिन सवाल अभी भी खड़ा है: अगर हमें ViewModel में संदर्भ नहीं रखना चाहिए, तो AndroidViewModel वर्ग भी क्यों मौजूद है? इसका पूरा उद्देश्य अनुप्रयोग संदर्भ प्रदान करना है, है न?
एलेक्स बर्डनिकोव

7
@AlexBerdnikov व्यूमोडल के अंदर गतिविधि के संदर्भ का उपयोग करके मेमोरी लीक हो सकती है। तो AndroidViewModel क्लास का उपयोग करके आपको एप्लिकेशन संदर्भ द्वारा प्रदान किया जाएगा जो किसी भी मेमोरी लीक का कारण नहीं होगा (उम्मीद है)। तो AndroidViewModel का उपयोग करने से बेहतर हो सकता है कि यह गतिविधि के संदर्भ में हो। लेकिन फिर भी ऐसा करने से परीक्षण मुश्किल हो जाएगा। इस पर मेरा टेक है।
hushed_voice

1
मैं भंडार से कच्चे / फ़ोल्डर से फ़ाइल तक नहीं पहुँच सकता?
फुगोगुओ

15

मैं सीधे ViewModel में एक संदर्भ होने के बजाय क्या कर रहा था, मैंने संसाधन वर्ग जैसे कि प्रोपरवाइडर के रूप में प्रदाता कक्षाएं दीं, जो मुझे उन संसाधनों की आवश्यकता होती हैं, और मुझे उन प्रदाता वर्गों को मेरे ViewModel में इंजेक्ट किया गया था


1
मैं AppModule में डैगर के साथ ResourcesProvider का उपयोग कर रहा हूं। क्या यह अच्छा तरीका है कि संदर्भ को प्राप्त करने के लिए अच्छा संसाधन है। Povider या AndroidViewModel संसाधनों के लिए संदर्भ प्राप्त करना बेहतर है?
उस्मान राणा

@Vincent: ViewModel के अंदर Drawable पाने के लिए resourceProvider का उपयोग कैसे करें?
बुलमा

@Vegeta आप getDrawableRes(@DrawableRes int id)संसाधन विधि के अंदर की तरह एक विधि जोड़ देंगे
विन्सेन्ट विलियम्स

1
यह क्लीन आर्किटेक्चर दृष्टिकोण के खिलाफ जाता है जिसमें कहा गया है कि फ्रेमवर्क निर्भरताएं डोमेन लॉजिक (ViewModels) में सीमाओं को पार नहीं करना चाहिए।
इगोरगानापोलस्की

1
@IgorGanapolsky VMs बिल्कुल डोमेन तर्क नहीं हैं। डोमेन लॉजिक अन्य वर्ग हैं जैसे कि कुछ को नाम देने के लिए इंटरप्रिटर्स और रिपॉजिटरी। VMs "गोंद" श्रेणी में आते हैं क्योंकि वे आपके डोमेन के साथ बातचीत करते हैं, लेकिन सीधे नहीं। यदि आपका VM आपके डोमेन का हिस्सा है, तो आपको इस बात पर पुनर्विचार करना चाहिए कि आप पैटर्न का उपयोग कैसे कर रहे हैं क्योंकि आप उन्हें बहुत अधिक जिम्मेदारी दे रहे हैं।
मृदज़िंस्की

9

TL; DR: अपने ViewModels में डैगर के माध्यम से एप्लिकेशन के संदर्भ को इंजेक्ट करें और संसाधनों को लोड करने के लिए इसका उपयोग करें। यदि आपको छवियों को लोड करने की आवश्यकता है, तो डेटाबेसिंग विधियों से तर्कों के माध्यम से दृश्य उदाहरण पास करें और उस दृश्य संदर्भ का उपयोग करें।

MVVM एक अच्छी वास्तुकला है और यह निश्चित रूप से Android विकास का भविष्य है, लेकिन कुछ चीजें हैं जो अभी भी हरे हैं। उदाहरण के लिए एक MVVM आर्किटेक्चर में लेयर कम्युनिकेशन को लें, मैंने विभिन्न डेवलपर्स (बहुत अच्छी तरह से ज्ञात डेवलपर्स) को अलग-अलग परतों को अलग-अलग तरीकों से संप्रेषित करने के लिए LiveData का उपयोग किया है। उनमें से कुछ यूआई के साथ ViewModel को संवाद करने के लिए LiveData का उपयोग करते हैं, लेकिन फिर वे रिपॉजिटरी के साथ संवाद करने के लिए कॉलबैक इंटरफेस का उपयोग करते हैं, या उनके पास इंटरेक्टर्स / यूसेजकेस हैं और वे उनके साथ संवाद करने के लिए लाइवडेटा का उपयोग करते हैं। यहाँ इंगित करें, यह है कि सब कुछ 100% परिभाषित नहीं है

यह कहा जा रहा है, आपकी विशिष्ट समस्या के साथ मेरा दृष्टिकोण डिव के माध्यम से एक अनुप्रयोग के संदर्भ उपलब्ध है, मेरे ViewModels में उपयोग करने के लिए अपने तार से स्ट्रिंग जैसी चीजें प्राप्त करने के लिए। xml

यदि मैं छवि लोडिंग से निपट रहा हूं, तो मैं डेटाबाइंडिंग एडाप्टर विधियों से व्यू ऑब्जेक्ट से गुजरने की कोशिश करता हूं और छवियों को लोड करने के लिए व्यू के संदर्भ का उपयोग करता हूं। क्यों? क्योंकि कुछ तकनीकें (उदाहरण के लिए ग्लाइड) मुद्दों में चल सकती हैं यदि आप छवियों को लोड करने के लिए एप्लिकेशन के संदर्भ का उपयोग करते हैं।

आशा है कि इससे सहायता मिलेगी!


5
TL; DR शीर्ष पर होना चाहिए
जैक्स कोर्ट्स

1
आपके उत्तर के लिए धन्यवाद। हालाँकि, आप संदर्भ को इंजेक्ट करने के लिए डैगर का उपयोग क्यों करेंगे यदि आप अपने व्यूमॉडल को androidviewmodel से बढ़ा सकते हैं और बिलिन के संदर्भ का उपयोग कर सकते हैं जो कक्षा में ही प्रदान करता है? विशेष रूप से खंजर और MVVM को एक साथ काम करने के लिए बॉयलरप्लेट कोड की हास्यास्पद मात्रा पर विचार करने से अन्य समाधान बहुत स्पष्ट लगता है। इस पर आपके विचार क्या हैं?
जोसिप डोमज़ेट

8

जैसा कि अन्य लोगों ने उल्लेख किया है, AndroidViewModelकि आप एप्लिकेशन प्राप्त करने के लिए किस से प्राप्त कर सकते हैं, Contextलेकिन जो मैं टिप्पणियों में इकट्ठा करता हूं, आप @drawableअपने भीतर से हेरफेर करने की कोशिश कर रहे हैं, ViewModelजो उद्देश्य एमवीवीएम को हराता है।

सामान्य तौर पर, Contextआपके ViewModelलगभग सार्वभौमिक रूप से एक होने की आवश्यकता का सुझाव आपको पुनर्विचार पर विचार करना चाहिए कि आप अपने Viewऔर अपने बीच के तर्क को कैसे विभाजित करते हैंViewModels

ViewModelसमाधानों को हल करने और गतिविधि / टुकड़े करने के लिए उन्हें खिलाने के बजाय , Fragment / गतिविधि के पास मौजूद डेटा पर आधारित ड्राफ़्ट को हथकंडा करने पर विचार करें ViewModel। कहो, आपको राज्य के लिए / बंद दृश्य में प्रदर्शित करने के लिए अलग-अलग दराज की आवश्यकता है - यह वह है ViewModelजो (शायद बूलियन) राज्य को पकड़ना चाहिए, लेकिन यह हैView ड्रॉबल का चयन करने के लिए उसके अनुसार व्यवसाय है।

यह DataBinding के साथ काफी आसान किया जा सकता है :

<ImageView
...
app:src="@{viewModel.isOn ? @drawable/switch_on : @drawable/switch_off}"
/>

यदि आपके पास अधिक राज्य और ड्रॉबल्स हैं, तो लेआउट फ़ाइल में अनिर्दिष्ट तर्क से बचने के लिए आप एक कस्टम बाइंडिंग एडाप्टर लिख सकते हैं जो अनुवाद करता है, कहता है, EnumमानR.drawable.* (जैसे कार्ड सूट)

या हो सकता है आप की जरूरत Contextकुछ घटक है कि आप के भीतर उपयोग के लिए अपने ViewModel- तो, बाहर घटक बनाने ViewModelऔर में इसे पारित आप डि, या एकमात्र उपयोग कर सकते हैं, या पैदा करते हैं। ContextInitialising से पहले निर्भर घटक सही ViewModelमें Fragment/ Activity

क्यों परेशान करें: Contextएक एंड्रॉइड-विशिष्ट चीज है, और उन पर निर्भर करता ViewModelहै एक बुरा अभ्यास है: वे इकाई परीक्षण के रास्ते में खड़े हैं। दूसरी ओर, आपके स्वयं के घटक / सेवा इंटरफेस पूरी तरह से आपके नियंत्रण में हैं, ताकि आप उन्हें आसानी से परीक्षण के लिए मॉक कर सकें।


5

अनुप्रयोग संदर्भ का संदर्भ है, हालांकि इसमें Android विशिष्ट कोड है

अच्छी खबर, आप उपयोग कर सकते हैं Mockito.mock(Context.class)और संदर्भ को वापस कर सकते हैं जो आप परीक्षणों में चाहते हैं!

तो ViewModelजैसा कि आप सामान्य रूप से करते हैं, वैसे ही उपयोग करें , और ViewModelProviders.Factory के माध्यम से ApplicationContext दें।


3

आप getApplication().getApplicationContext()ViewModel के भीतर से आवेदन संदर्भ का उपयोग कर सकते हैं । यह वही है जो आपको संसाधनों, वरीयताओं आदि को एक्सेस करने की आवश्यकता है।


मैं अपने सवाल को कम करने के लिए अनुमान लगाता हूं। क्या व्यूमाडेल के अंदर एक संदर्भ संदर्भ होना बुरा है (क्या यह परीक्षण को प्रभावित नहीं करता है?) और क्या AndroidViewModel वर्ग किसी भी तरह से डैगर को प्रभावित करेगा? क्या यह गतिविधि जीवन चक्र से बंधा नहीं है? मैं घटकों के जीवनचक्र को नियंत्रित करने के लिए डैगर का उपयोग कर रहा हूं
विन्सेन्ट विलियम्स

14
ViewModelवर्ग नहीं है getApplicationविधि।
बीराल

4
नहीं, लेकिन AndroidViewModelकरता है

1
लेकिन आपको इसके कंस्ट्रक्टर में एप्लिकेशन इंस्टेंस को पास करना होगा, यह एप्लीकेशन इंस्टेंस को एक्सेस करने की तरह ही है
जॉन सरदिन्हा

2
यह एप्लिकेशन संदर्भ के लिए एक बड़ी समस्या नहीं है। आप गतिविधि / विखंडन संदर्भ नहीं चाहते हैं क्योंकि यदि आप खंड / गतिविधि नष्ट हो गए हैं और दृश्य मॉडल अभी भी कोई भी प्रासंगिक संदर्भ नहीं है तो आप बोर हो गए हैं। लेकिन आप कभी भी APPLICATION संदर्भ को नष्ट नहीं करेंगे, लेकिन VM के पास अभी भी इसका संदर्भ है। सही? क्या आप ऐसे परिदृश्य की कल्पना कर सकते हैं जहां आपका ऐप बाहर निकलता है लेकिन व्यूमोडल नहीं है? :)
user1713450

3

आपको अपने ViewModel में Android से संबंधित वस्तुओं का उपयोग नहीं करना चाहिए क्योंकि ViewModel का उपयोग करने का उद्देश्य जावा कोड और एंड्रॉइड कोड को अलग करना है ताकि आप अपने व्यवसाय तर्क को अलग से परख सकें और आपके पास Android घटकों और आपके व्यावसायिक तर्क की एक अलग परत होगी और डेटा, आपके ViewModel में संदर्भ नहीं होना चाहिए क्योंकि इससे क्रैश हो सकता है


2
यह एक उचित अवलोकन है, लेकिन बैकएंड पुस्तकालयों में से कुछ को अभी भी एप्लिकेशन संदर्भों की आवश्यकता है, जैसे कि मीडियास्टोर। नीचे 4gus71n द्वारा उत्तर यह बताता है कि समझौता कैसे करना है।
ब्रायन डब्ल्यू। वैगनर

1
हां, आप एप्लिकेशन संदर्भ का उपयोग कर सकते हैं लेकिन गतिविधियों के संदर्भ में नहीं, क्योंकि अनुप्रयोग संदर्भ पूरे जीवन चक्र में रहता है, लेकिन गतिविधि संदर्भ के रूप में किसी भी अतुल्यकालिक प्रक्रिया को पास करने के रूप में गतिविधि का परिणाम नहीं हो सकता है स्मृति लीक में परिणाम - संदर्भ मेरी पोस्ट में वर्णित गतिविधि है संदर्भ। लेकिन आपको फिर भी किसी भी अतुल्यकालिक प्रक्रिया के संदर्भ में नहीं होने का ध्यान रखना चाहिए, भले ही यह एप्लिकेशन संदर्भ हो।
रोहित शर्मा

2

कक्षा SharedPreferencesका उपयोग करते समय मुझे परेशानी हो रही थी ViewModelइसलिए मैंने ऊपर दिए गए उत्तरों से सलाह ली और निम्नलिखित का उपयोग किया AndroidViewModel। अब सब कुछ बहुत अच्छा लग रहा है

के लिए AndroidViewModel

import android.app.Application;
import android.content.Context;
import android.content.SharedPreferences;

import androidx.lifecycle.AndroidViewModel;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.preference.PreferenceManager;

public class HomeViewModel extends AndroidViewModel {

    private MutableLiveData<String> some_string;

    public HomeViewModel(Application application) {
        super(application);
        some_string = new MutableLiveData<>();
        Context context = getApplication().getApplicationContext();
        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
        some_string.setValue("<your value here>"));
    }

}

और इसमें Fragment

import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProviders;


public class HomeFragment extends Fragment {


    public View onCreateView(@NonNull LayoutInflater inflater,
                             ViewGroup container, Bundle savedInstanceState) {
        final View root = inflater.inflate(R.layout.fragment_home, container, false);
        HomeViewModel homeViewModel = ViewModelProviders.of(this).get(HomeViewModel.class);
        homeViewModel.getAddress().observe(getViewLifecycleOwner(), new Observer<String>() {
            @Override
            public void onChanged(@Nullable String address) {


            }
        });
        return root;
    }
}

0

मैंने इसे इस तरह बनाया है:

@Module
public class ContextModule {

    @Singleton
    @Provides
    @Named("AppContext")
    public Context provideContext(Application application) {
        return application.getApplicationContext();
    }
}

और फिर मैंने अभी AppComponent the ContextModule.class में जोड़ा:

@Component(
       modules = {
                ...
               ContextModule.class
       }
)
public interface AppComponent extends AndroidInjector<BaseApplication> {
.....
}

और फिर मैंने अपने ViewModel में संदर्भ इंजेक्ट किया:

@Inject
@Named("AppContext")
Context context;

0

निम्नलिखित पैटर्न का उपयोग करें:

class NameViewModel(
val variable:Class,application: Application):AndroidViewModel(application){
   body...
}

0

ViewModel में एक Context इंजेक्ट करने में समस्या यह है कि Context किसी भी समय बदल सकता है, स्क्रीन रोटेशन, नाइट मोड या सिस्टम लैंग्वेज पर निर्भर करता है, और कोई भी रिटर्न किए गए संसाधन तदनुसार बदल सकते हैं। एक साधारण संसाधन आईडी को वापस करने से अतिरिक्त मापदंडों के लिए समस्या होती है, जैसे गेटस्ट्रीमिंग प्रतिस्थापन। उच्च-स्तरीय परिणाम लौटना और गतिविधि के लिए प्रतिपादन तर्क को आगे बढ़ाना कठिन होता है।

मेरा समाधान ViewModel उत्पन्न करना और एक फ़ंक्शन को वापस करना है जो बाद में गतिविधि के संदर्भ के माध्यम से चलाया जाता है। कोटलिन का सिन्गनेटिक शुगर इसे अविश्वसनीय रूप से आसान बनाता है!

ViewModel.kt:

// connectedStatus holds a function that calls Context methods
// `this` can be elided
val connectedStatus = MutableLiveData<Context.() -> String> {
  // initial value
  this.getString(R.string.connectionStatusWaiting)
}
connectedStatus.postValue {
  this.getString(R.string.connectionStatusConnected, brand)
}
Activity.kt  // is a Context

override fun onCreate(_: Bundle?) {
  connectionViewModel.connectedStatus.observe(this) { it ->
   // runs the posted value with the given Context receiver
   txtConnectionStatus.text = this.run(it)
  }
}

यह ViewModel को यूनिट के परीक्षणों द्वारा सत्यापित प्रदर्शित जानकारी की गणना करने के लिए तर्क के सभी को पकड़ने की अनुमति देता है, जिसमें गतिविधि बग को छिपाने के लिए कोई आंतरिक तर्क के साथ एक बहुत ही सरल प्रतिनिधित्व है।


और डेटाबाइंडिंग समर्थन को सक्षम करने के लिए, आप बस एक साधारण बाइंडिंग एडेप्टर जैसे जोड़ते हैं:@BindingAdapter("android:text") fun setText(view: TextView, value: Context.() -> String) { view.text = view.context.run(value) }
hufman
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.