getApplication () बनाम getApplicationContext ()


417

मुझे इसका कोई संतोषजनक उत्तर नहीं मिला, इसलिए हम यहाँ जाते हैं: क्या सौदा है Activity/Service.getApplication()और Context.getApplicationContext()?

हमारे आवेदन में, दोनों एक ही वस्तु को लौटाते हैं। एक में ActivityTestCaseहालांकि, आवेदन मजाक कर देगा getApplication()नकली के साथ वापस आ, लेकिन getApplicationContextअभी भी एक अलग संदर्भ उदाहरण (एक एंड्रॉयड द्वारा इंजेक्शन) वापस आ जाएगी। क्या वह बग है? क्या यह उद्देश्य पर है?

मैं पहली जगह में अंतर भी नहीं समझता। क्या परीक्षण सूट के बाहर ऐसे मामले हैं जहां दोनों कॉल विभिन्न वस्तुओं के साथ वापस आ सकते हैं? कब और क्यों? इसके अलावा, getApplicationपर Activityऔर पर क्यों परिभाषित किया Serviceगया है Context? क्या हमेशा कहीं से भी एक वैध आवेदन उदाहरण उपलब्ध नहीं होना चाहिए ?


8
अच्छा प्रश्न। परीक्षण सामान एक रहस्य का एक सा है (जैसा कि आप अच्छी तरह से जानते हैं)। लेकिन मुझे आश्चर्य है कि अगर आप अपने ऐप में कोई ऑब्जेक्ट स्पष्ट रूप से नहीं बनाते हैं तो इन दोनों मेथड कॉल्स में कोई अंतर दिखाई देता है Application
क्रिस्टोफर ओर्र

जवाबों:


366

बहुत ही रोचक सवाल। मुझे लगता है कि यह मुख्य रूप से अर्थ अर्थ है, और ऐतिहासिक कारणों से भी हो सकता है।

यद्यपि वर्तमान एंड्रॉइड गतिविधि और सेवा कार्यान्वयन में, getApplication()और getApplicationContext()समान ऑब्जेक्ट वापस करते हैं, इस बात की कोई गारंटी नहीं है कि यह हमेशा मामला होगा (उदाहरण के लिए, एक विशिष्ट विक्रेता कार्यान्वयन में)।

इसलिए यदि आप चाहते हैं कि आप जिस एप्लिकेशन वर्ग को मेनिफेस्ट में पंजीकृत करें , तो आपको कभी भी उसे कॉल नहीं करना चाहिए getApplicationContext()और उसे अपने आवेदन में नहीं डालना चाहिए , क्योंकि यह एप्लिकेशन इंस्टेंस नहीं हो सकता है (जिसे आपने स्पष्ट रूप से परीक्षण ढांचे के साथ अनुभव किया है)।

getApplicationContext()पहले स्थान पर क्यों है ?

getApplication()केवल गतिविधि वर्ग और सेवा वर्ग में उपलब्ध है, जबकि getApplicationContext()संदर्भ वर्ग में घोषित किया गया है।

इसका वास्तव में एक मतलब है: जब एक प्रसारण रिसीवर में कोड लिखना, जो कि एक संदर्भ नहीं है, लेकिन इसकी ऑनरिव विधि में एक संदर्भ दिया गया है, तो आप केवल कॉल कर सकते हैं getApplicationContext()। जिसका अर्थ यह भी है कि किसी ब्रॉडकास्टसीवर में आपको अपने एप्लिकेशन तक पहुंचने की गारंटी नहीं है।

एंड्रॉइड कोड को देखते समय, आप देखते हैं कि संलग्न होने पर, एक गतिविधि को एक आधार संदर्भ और एक आवेदन प्राप्त होता है, और वे अलग-अलग पैरामीटर हैं। getApplicationContext()प्रतिनिधियों यह करने के लिए कहते हैं baseContext.getApplicationContext()

एक और बात: प्रलेखन का कहना है कि यह ज्यादातर मामलों में, आपको एप्लिकेशन को उप-वर्ग करने की आवश्यकता नहीं होनी चाहिए:

आमतौर पर उपवर्ग की कोई आवश्यकता नहीं है Application। अधिकांश स्थिति में, स्थिर एकल एकल अधिक कार्यात्मक तरीके से समान कार्यक्षमता प्रदान कर सकते हैं। यदि आपके सिंगलटन को एक वैश्विक संदर्भ की आवश्यकता है (उदाहरण के लिए प्रसारण रिसीवर को पंजीकृत करने के लिए), तो इसे पुनः प्राप्त करने के लिए फ़ंक्शन को सिंगलटन का निर्माण करते समय Contextआंतरिक रूप से उपयोग किया जा सकता है Context.getApplicationContext()

मुझे पता है कि यह एक सटीक और सटीक उत्तर नहीं है, लेकिन फिर भी, क्या यह आपके सवाल का जवाब देता है?


89
@ Piwa Don't: डॉक्टर की बात मत सुनो। सबक्लासिंग android.app.Applicationसुपर हेल्प फुल है। उदाहरण के लिए मुझे डेटाबेस को शुरू करने में अंतहीन समस्याएं थीं। एक बार जब Application.onCreateयह एक आकर्षण की तरह काम में ले जाया गया । अब मैं सभी सिस्टम में व्यापक इनिशियलाइज़ेशन करता Applicationहूँ और मैं इसके बिना कोई दूसरा ऐप नहीं लिखूंगा।
मार्टिन

9
@Martin डॉक्स के बारे में नहीं सुनने का आम तौर पर मतलब है कि आपका कोड भविष्य में टूट सकता है, या अब भी अप्रत्याशित परिस्थितियों में, पोर्टेबिलिटी खो सकता है, खराब प्रदर्शन कर सकता है, प्लेटफ़ॉर्म डेवलपर्स को एक लाभकारी बदलाव करने से रोकता है (जो आपके द्वारा गलत तरीके से बनाई गई धारणा को तोड़ता है, हालांकि यह था केवल वर्तमान कार्यान्वयन पर आधारित है, डॉक्स नहीं)। मुझे लगता है कि यह बहुत बुरा व्यवहार है और सलाह का बहुत बुरा टुकड़ा है।
पलक

17
@Palec: "आमतौर पर एप्लिकेशन को उप-वर्ग करने की कोई आवश्यकता नहीं है।" - यह सिर्फ संकेत है। मैं अभी भी इच्छित तरीके से आधिकारिक रूप से प्रलेखित कार्यक्षमता का उपयोग करता हूं। - मैंने शुरुआत में उन "स्टैटिक सिंग्लेटन्स" का इस्तेमाल किया और वे एक दर्द में बदल गए ... - आलसी इनिशियलाइजेशन की समस्याएँ हैं। विशेष रूप से जब इंस्ट्रूमेंटेशन परीक्षणों के साथ उपयोग किया जाता है। - मेरे पास अभी भी मॉड्युलैरिटी के लिए वे सिंगलेट्स हैं, लेकिन मैं उन्हें android.app.Application उपवर्ग के onCreate में ब्लॉक कर देता हूं। - एक जादू की तरह काम करता है।
मार्टिन

9
@ मर्टिन मुझे यह स्पष्ट करना चाहिए: मेरी प्रतिक्रिया केवल पहले वाक्य से संबंधित है। "डॉक्टर की बात मत सुनो।" यह आम तौर पर सलाह का बहुत खतरनाक टुकड़ा है। लेकिन "यह सिर्फ एक संकेत है - आप इस मामले में डॉक्टर की उपेक्षा कर सकते हैं यदि आपके पास कोई कारण है और मैं आपको एक दिखाऊंगा ..." मुझे बिल्कुल ठीक लगता है।
पेलेक

3
"जब एक प्रसारण रिसीवर में कोड लिखना, जो कि एक संदर्भ नहीं है, लेकिन इसकी ऑनरेक्टिव विधि में एक संदर्भ दिया गया है, तो आप केवल getApplicationContext () कह सकते हैं। इसका मतलब यह भी है कि आप किसी ब्रॉडकास्टसीवर में अपने आवेदन तक पहुंच की गारंटी नहीं है। " । ब्रॉडकास्टसीवर में मेरे आवेदन वर्ग तक पहुँचने के लिए हम क्या कर सकते हैं?
डॉ। जकी

30

तुलना getApplication()और getApplicationContext()

getApplicationएक रिटर्न Applicationवस्तु है जो आप जैसे कुछ डिवाइस स्थितियों के लिए अपने वैश्विक आवेदन राज्य और प्रतिक्रिया का प्रबंधन करने की अनुमति देगा onLowMemory()और onConfigurationChanged()

getApplicationContextवैश्विक अनुप्रयोग संदर्भ लौटाता है - अन्य संदर्भों से अंतर यह है कि उदाहरण के लिए, जब आपकी गतिविधि समाप्त हो जाती है, तो एक गतिविधि संदर्भ एंड्रॉइड द्वारा नष्ट (या अन्यथा अनुपलब्ध) हो सकता है। एप्लिकेशन संदर्भ तब भी उपलब्ध रहता है जब आपकी एप्लिकेशन ऑब्जेक्ट मौजूद होती है (जो किसी विशिष्ट से जुड़ी नहीं होती है Activity) इसलिए आप इसका उपयोग नोटिफिकेशन जैसी चीजों के लिए कर सकते हैं जिनके लिए एक संदर्भ की आवश्यकता होती है जो लंबी अवधि और क्षणिक UI ऑब्जेक्ट से स्वतंत्र हो।

मुझे लगता है कि यह इस बात पर निर्भर करता है कि आपका कोड क्या कर रहा है या नहीं ये समान हो सकता है - हालांकि सामान्य उपयोग में, मैं उनसे अलग होने की उम्मीद करूंगा।


19
लेकिन एक Application है एक Context(इसे से विरासत), और रनटाइम पर, दोनों तरीकों एक ही उदाहरण लौट आते हैं। तो क्या अंतर है?
मथायस

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

16
मुझे लगता है कि आप मेरे सवाल का गलत इस्तेमाल कर रहे होंगे। मैं एक Activityसंदर्भ और एक Applicationसंदर्भ के बीच का अंतर नहीं पूछ रहा हूं । मैं Application(जो वैश्विक, अद्वितीय अनुप्रयोग संदर्भ है) और जो कुछ भी getApplicationContextरिटर्न देता है , उसके बीच अंतर बता रहा हूं । उत्तरार्द्ध वास्तव में एंड्रॉइड 1.6 से पहले गैर-कार्यात्मक था; यह हमेशा लौटता था null
मथायस

1
@Matthias मेरी राय में यह अभी भी प्रासंगिक है। Android सिस्टम द्वारा ही Context को इंजेक्ट (कार्यान्वित) किया जाता है, जबकि Application विरासत में मिलता है और विस्तारित होता है। एप्लिकेशन क्लास को आसानी से मॉक किया जा सकता है (जैसा कि आपके द्वारा कहा गया है) तो क्या यह एक सुरक्षित शर्त नहीं है कि यह दर्शाता है कि इसे प्राप्त करने के लिए एप्लिकेशन क्लास कुछ "जादू" (परीक्षण परियोजना में) करता है, संभवतः इंजेक्शन वाले संदर्भ को अनदेखा कर रहा है?
ऑड्रियस

3
फिर से आना? मुझे क्षमा करें, मैं अभी भी नहीं देखता कि मेरे प्रश्न का उत्तर कैसे है।
मथायस

30

ऐसा लगता है कि संदर्भ के साथ क्या करना है। से प्राप्त अधिकांश कक्षाएं Contextवास्तव में एक हैं ContextWrapper, जो अनिवार्य रूप से रैपर द्वारा परिवर्तनों के साथ, एक और संदर्भ को प्रस्तुत करती हैं।

संदर्भ एक सामान्य अमूर्तता है जो मॉकिंग और समीपता का समर्थन करता है। चूंकि कई संदर्भ सीमित-आजीवन वस्तु जैसे कि एक से बंधे होते हैं Activity, इसलिए भविष्य में सूचनाओं के लिए पंजीकरण जैसे उद्देश्यों के लिए, एक लंबे समय तक रहने वाले संदर्भ प्राप्त करने का एक तरीका होना चाहिए। द्वारा प्राप्त किया जाता है Context.getApplicationContext()। एक तार्किक कार्यान्वयन वैश्विक Applicationवस्तु को वापस करने के लिए है , लेकिन कुछ भी एक संदर्भ कार्यान्वयन को इसके बजाय एक उपयुक्त जीवनकाल के साथ एक आवरण या प्रॉक्सी को वापस करने से रोकता है।

गतिविधियाँ और सेवाएँ किसी Applicationवस्तु के साथ विशेष रूप से जुड़ी होती हैं। इस बात की उपयोगिता, मेरा मानना ​​है कि, आप एक कस्टम वर्ग से प्राप्त होने वाले मेनिफेस्ट में बना सकते हैं और पंजीकरण कर सकते हैं और Applicationनिश्चित Activity.getApplication()कर Service.getApplication()सकते हैं या उस विशिष्ट प्रकार की उस विशिष्ट वस्तु को वापस कर देंगे, जिसे आप अपने व्युत्पन्न Applicationवर्ग में डाल सकते हैं और जो कुछ भी उपयोग कर सकते हैं कस्टम उद्देश्य।

दूसरे शब्दों में, getApplication()किसी Applicationवस्तु को वापस करने की गारंटी है , जबकि getApplicationContext()इसके बजाय एक प्रॉक्सी वापस करने के लिए स्वतंत्र है।


जब आप कहते हैं "संदर्भ एक सामान्य अमूर्तता है जो मॉकिंग और समीपता का समर्थन करता है" तो आप "प्रॉक्सिंग" से वास्तव में क्या मतलब है? क्या आप मुझे कुछ संदर्भों की ओर इशारा कर सकते हैं? मुझे पूरा प्रसंग काफी जटिल लगता है।
टियागो

@Tiago इस उत्तर मदद कर सकते हैं बेहतर समझते हैं: stackoverflow.com/questions/10641144/...
सुपर उपयोगकर्ता

-13

प्रश्न का उत्तर देने के लिए, GetApplication () एक एप्लिकेशन ऑब्जेक्ट लौटाता है और GetApplicationContext () एक संदर्भ ऑब्जेक्ट लौटाता है। आपकी अपनी टिप्पणियों के आधार पर, मैं मानूंगा कि दोनों के संदर्भ समान हैं (जैसे कि पर्दे के पीछे अनुप्रयोग वर्ग आधार वर्ग के संदर्भ भाग को पॉप्युलेट करने के लिए बाद के फ़ंक्शन को कॉल करता है या कुछ बराबर कार्रवाई होती है)। यह वास्तव में कोई फर्क नहीं पड़ता कि आप किस फ़ंक्शन को कॉल करते हैं यदि आपको केवल एक संदर्भ की आवश्यकता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.