मैंने यह उत्तर '09 में वापस लिखा था जब एंड्रॉइड अपेक्षाकृत नया था, और एंड्रॉइड विकास में कई अच्छी तरह से स्थापित क्षेत्र नहीं थे। मैंने इस पोस्ट के निचले भाग में एक लंबी परिशिष्ट जोड़ दिया है, कुछ आलोचना को संबोधित किया है, और मुझे उप-अभिलेखन अनुप्रयोग के बजाय सिंगलेट्स के उपयोग के साथ एक दार्शनिक असहमति का विवरण है। इसे अपने जोखिम पर पढ़ें।
मूल ANSWER:
अधिक सामान्य समस्या जो आप सामना कर रहे हैं वह यह है कि कई गतिविधियों और आपके आवेदन के सभी हिस्सों में राज्य को कैसे बचाया जाए। एक स्थिर चर (उदाहरण के लिए, एक सिंगलटन) इसे प्राप्त करने का एक सामान्य जावा तरीका है। हालाँकि, मैंने पाया है कि एंड्रॉइड में एक अधिक सुरुचिपूर्ण तरीका आपके राज्य को एप्लिकेशन संदर्भ के साथ जोड़ना है।
जैसा कि आप जानते हैं, प्रत्येक गतिविधि एक संदर्भ भी है, जो व्यापक अर्थों में इसके निष्पादन पर्यावरण के बारे में जानकारी है। आपके आवेदन में एक संदर्भ भी है, और एंड्रॉइड गारंटी देता है कि यह आपके आवेदन में एकल उदाहरण के रूप में मौजूद होगा।
ऐसा करने का तरीका android.app.Application का अपना उपवर्ग बनाना है , और फिर उस वर्ग को अपने प्रकट में एप्लिकेशन टैग में निर्दिष्ट करें। अब एंड्रॉइड स्वचालित रूप से उस वर्ग का एक उदाहरण बना देगा और इसे आपके संपूर्ण एप्लिकेशन के लिए उपलब्ध करा देगा। आप किसी भी विधि context
का उपयोग करके इसे एक्सेस कर सकते हैं Context.getApplicationContext()
( Activity
एक विधि भी प्रदान करता है getApplication()
जिसका सटीक समान प्रभाव होता है)। निम्नलिखित का पालन करने के लिए एक अत्यंत सरल उदाहरण दिया गया है:
class MyApp extends Application {
private String myState;
public String getState(){
return myState;
}
public void setState(String s){
myState = s;
}
}
class Blah extends Activity {
@Override
public void onCreate(Bundle b){
...
MyApp appState = ((MyApp)getApplicationContext());
String state = appState.getState();
...
}
}
यह अनिवार्य रूप से एक स्थिर चर या सिंगलटन का उपयोग करने के समान है, लेकिन मौजूदा एंड्रॉइड फ्रेमवर्क में काफी अच्छी तरह से एकीकृत करता है। ध्यान दें कि यह प्रक्रियाओं में काम नहीं करेगा (क्या आपका ऐप उन दुर्लभ लोगों में से एक होना चाहिए जिनके पास कई प्रक्रियाएं हैं)।
ऊपर दिए गए उदाहरण से ध्यान देने योग्य बात; मान लीजिए कि हमने इसके बजाय कुछ ऐसा किया है:
class MyApp extends Application {
private String myState = /* complicated and slow initialization */;
public String getState(){
return myState;
}
}
अब यह धीमी गति से इनिशियलाइज़ेशन (जैसे डिस्क को मारना, नेटवर्क से टकराना, कुछ भी ब्लॉक करना आदि) हर बार किया जाएगा। आप सोच सकते हैं, ठीक है, यह प्रक्रिया के लिए केवल एक बार है और मुझे वैसे भी लागत का भुगतान करना होगा, है ना? उदाहरण के लिए, जैसा कि डायने हैकॉर्न नीचे उल्लेख करते हैं, आपकी प्रक्रिया के लिए पूरी तरह से संभव है कि एक पृष्ठभूमि घटना की घटना को संभालने के लिए तत्काल-अन्याय हो। यदि आपकी प्रसारण प्रक्रिया को इस स्थिति की कोई आवश्यकता नहीं है, तो आपने संभावित रूप से कुछ भी नहीं के लिए जटिल और धीमे संचालन की एक पूरी श्रृंखला की है। आलसी तात्कालिकता यहाँ खेल का नाम है। निम्नलिखित अनुप्रयोग का उपयोग करने का एक अधिक जटिल तरीका है जो किसी भी चीज़ के लिए अधिक समझ में आता है लेकिन उपयोगों में सबसे सरल है:
class MyApp extends Application {
private MyStateManager myStateManager = new MyStateManager();
public MyStateManager getStateManager(){
return myStateManager ;
}
}
class MyStateManager {
MyStateManager() {
/* this should be fast */
}
String getState() {
/* if necessary, perform blocking calls here */
/* make sure to deal with any multithreading/synchronicity issues */
...
return state;
}
}
class Blah extends Activity {
@Override
public void onCreate(Bundle b){
...
MyStateManager stateManager = ((MyApp)getApplicationContext()).getStateManager();
String state = stateManager.getState();
...
}
}
हालांकि मैं यहां अधिक सुंदर समाधान के रूप में सिंगलटन का उपयोग करने के लिए एप्लिकेशन सबक्लासिंग को प्राथमिकता देता हूं, लेकिन मैं यह चाहूंगा कि डेवलपर सिंग्लेटन्स का उपयोग करें यदि वास्तव में प्रदर्शन के माध्यम से बिल्कुल नहीं सोचें और एप्लिकेशन सबक्लास के साथ संबद्ध राज्य के निहितार्थों को बढ़ाएं।
नोट 1: इसके अलावा, जैसा कि एंटीकैफ़ ने टिप्पणी की थी, आपके एप्लिकेशन को आपके एप्लिकेशन को ओवरराइड करने के लिए सही ढंग से टाई करने के लिए, प्रकट फ़ाइल में एक टैग आवश्यक है। फिर से, अधिक जानकारी के लिए Android डॉक्स देखें। एक उदाहरण:
<application
android:name="my.application.MyApp"
android:icon="..."
android:label="...">
</application>
नोट 2: user608578 नीचे पूछता है कि यह मूल वस्तु जीवन चक्रों के प्रबंधन के साथ कैसे काम करता है। मैं थोड़ी सी भी एंड्रॉइड के साथ मूल कोड का उपयोग करने की गति पर नहीं हूं, और मैं यह जवाब देने के लिए योग्य नहीं हूं कि मेरे समाधान के साथ कैसे बातचीत होगी। यदि किसी के पास इसका उत्तर है, तो मैं उन्हें श्रेय देने और अधिकतम दृश्यता के लिए इस पोस्ट में जानकारी रखने को तैयार हूं।
परिशिष्ट:
जैसा कि कुछ लोगों ने उल्लेख किया है, यह लगातार राज्य के लिए एक समाधान नहीं है , कुछ जो मुझे शायद मूल उत्तर में अधिक जोर देना चाहिए था। यानी यह उपयोगकर्ता को बचाने के लिए या अन्य सूचनाओं के लिए एक समाधान नहीं है, जिसका अर्थ है आवेदन जीवन भर के लिए जारी रखा जाए। इस प्रकार, मैं किसी भी समय मारे जाने वाले एप्लिकेशन, आदि से संबंधित अधिकांश आलोचनाओं पर विचार करता हूं ..., मूट, कुछ भी जो कभी भी डिस्क को बनाए रखने की आवश्यकता होती है, को एप्लिकेशन उपवर्ग के माध्यम से संग्रहीत नहीं किया जाना चाहिए। इसका अर्थ है अस्थायी, आसानी से पुन: उपयोग करने योग्य अनुप्रयोग स्थिति (उपयोगकर्ता उदाहरण के लिए लॉग इन किया जाता है) और ऐसे घटक जो एकल उदाहरण (उदाहरण के लिए एप्लिकेशन नेटवर्क प्रबंधक) हैं ( न कि सिंगलटन)!
डेटरमैन रेटो मीयर और डायने हैकॉर्न के साथ एक दिलचस्प बातचीत को इंगित करने के लिए पर्याप्त है जिसमें एप्लिकेशन उपवर्गों का उपयोग सिंगलटन पैटर्न के पक्ष में हतोत्साहित किया गया है। सोमाटिक ने पहले भी इस प्रकृति के बारे में कुछ बताया था, हालांकि मैंने उस समय इसे नहीं देखा था। एंड्रॉइड प्लेटफ़ॉर्म को बनाए रखने में रेटो और डायने की भूमिकाओं के कारण, मैं उनकी सलाह को अनदेखा करने की सलाह नहीं दे सकता। वे जो कहते हैं, जाता है। मैं आवेदन उपवर्गों पर सिंगलटन पसंद करने के संबंध में व्यक्त की गई राय से असहमत होना चाहता हूं। अपनी असहमति में, मैं सिंगल्सटन डिजाइन पैटर्न के इस स्टैक एक्सचेंज स्पष्टीकरण में वर्णित अवधारणाओं का सबसे अच्छा उपयोग करूंगा, ताकि मुझे इस उत्तर में शर्तों को परिभाषित न करना पड़े। मैं अत्यधिक लिंक को जारी रखने से पहले प्रोत्साहित करता हूं। बिन्दुवार:
डायने कहते हैं, "एप्लिकेशन से उपवर्ग का कोई कारण नहीं है। यह एकल बनाने से अलग नहीं है ..." यह पहला दावा गलत है। इसके दो मुख्य कारण हैं। 1) आवेदन वर्ग एक आवेदन डेवलपर के लिए एक बेहतर जीवनकाल गारंटी प्रदान करता है; यह आवेदन के जीवनकाल के लिए गारंटी है। एक सिंगलटन पूरी तरह से एप्लिकेशन के जीवनकाल से बंधा नहीं है (हालांकि यह प्रभावी रूप से है)। यह आपके औसत एप्लिकेशन डेवलपर के लिए एक गैर-मुद्दा हो सकता है, लेकिन मैं तर्क दूंगा कि यह बिल्कुल उसी प्रकार का अनुबंध है जिसे एंड्रॉइड एपीआई को पेश किया जाना चाहिए, और यह एंड्रॉइड सिस्टम को बहुत अधिक लचीलापन प्रदान करता है, साथ ही संबद्ध के जीवनकाल को न्यूनतम करके डेटा। 2) आवेदन वर्ग राज्य के लिए एकल उदाहरण धारक के साथ आवेदन डेवलपर प्रदान करता है, जो कि राज्य के एक सिंगलटन धारक से बहुत अलग है। मतभेदों की सूची के लिए, ऊपर सिंगलटन स्पष्टीकरण लिंक देखें।
डायने जारी है, "... भविष्य में आपको कुछ पछतावा होने की संभावना है क्योंकि आप पाते हैं कि आपका एप्लिकेशन ऑब्जेक्ट स्वतंत्र अनुप्रयोग तर्क का बड़ा पेचीदा गड़बड़ बन गया है।" यह निश्चित रूप से गलत नहीं है, लेकिन यह अनुप्रयोग उपवर्ग पर सिंगलटन चुनने का एक कारण नहीं है। डायने की कोई भी दलील यह तर्क नहीं देती है कि एक सिंगलटन का उपयोग करना एप्लिकेशन उपवर्ग से बेहतर है, वह यह स्थापित करने का प्रयास करता है कि एक सिंगलटन का उपयोग करना एप्लिकेशन उपवर्ग से अधिक बुरा नहीं है, जो मुझे विश्वास है कि गलत है।
वह जारी रखती है, "और यह स्वाभाविक रूप से आगे बढ़ता है कि आपको इन चीजों को कैसे प्रबंधित करना चाहिए - उन्हें मांग पर शुरुआती करना।" यह इस तथ्य को नजरअंदाज करता है कि ऐसा कोई कारण नहीं है कि आप एप्लिकेशन सबक्लास का उपयोग करके मांग पर आरंभ नहीं कर सकते। फिर कोई फर्क नहीं है।
डायने के साथ समाप्त होता है "फ्रेम में खुद के सभी साझा किए गए डेटा के लिए टन और टन के सिंगलनेट होते हैं जो इसे ऐप के लिए बनाए रखता है, जैसे कि लोड किए गए संसाधनों के कैश, वस्तुओं के पूल, आदि। यह बहुत अच्छा काम करता है।" मैं यह तर्क नहीं दे रहा हूं कि सिंग्लेटन्स का उपयोग ठीक काम नहीं कर सकता है या एक वैध विकल्प नहीं है। मैं यह तर्क दे रहा हूं कि सिंगलटन एंड्रॉइड सिस्टम के साथ एक एप्लिकेशन उपवर्ग का उपयोग करते हुए एक मजबूत अनुबंध प्रदान नहीं करता है, और आगे कहा गया है कि सिंगलेट्स का उपयोग आमतौर पर अनम्य डिजाइन को इंगित करता है, जो आसानी से संशोधित नहीं होता है, और सड़क के नीचे कई समस्याओं की ओर जाता है। IMHO, डेवलपर अनुप्रयोगों के लिए Android API प्रदान करता है मजबूत अनुबंध, Android के साथ प्रोग्रामिंग के सबसे आकर्षक और मनभावन पहलुओं में से एक है, और इससे शुरुआती डेवलपर को अपनाने में मदद मिली, जिसने आज इसे सफलता के लिए एंड्रॉइड प्लेटफॉर्म को निकाल दिया।
डायने ने नीचे भी टिप्पणी की है, अनुप्रयोग उपवर्गों का उपयोग करने के लिए एक अतिरिक्त नकारात्मक का उल्लेख करते हुए, वे कम प्रदर्शन कोड लिखने के लिए प्रोत्साहित या आसान बना सकते हैं। यह बहुत सही है, और मैंने इस उत्तर को यहां पूर्णता पर विचार करने के महत्व पर जोर देने के लिए संपादित किया है, और यदि आप एप्लिकेशन उपवर्ग का उपयोग कर रहे हैं तो सही दृष्टिकोण अपना रहे हैं। जैसा कि डायने कहते हैं, यह याद रखना महत्वपूर्ण है कि आपकी एप्लिकेशन लोड होने पर हर बार आपकी प्रक्रिया को तुरंत लोड किया जाएगा (एक साथ कई बार हो सकता है अगर आपका आवेदन कई प्रक्रियाओं में चलता है!) भले ही प्रक्रिया केवल पृष्ठभूमि प्रसारण के लिए भरी जा रही हो! प्रतिस्पर्धा। इसलिए यह महत्वपूर्ण है कि किसी भी प्रक्रिया को करने के लिए एक जगह के रूप में अपने आवेदन के साझा घटकों के लिए संकेत के लिए एक रिपॉजिटरी के रूप में अनुप्रयोग वर्ग का उपयोग करना अधिक महत्वपूर्ण है!
मैं आपको सिंगल्सटन के लिए निम्न सूची के साथ छोड़ देता हूं, जैसा कि पहले StackExchange लिंक से चुराया गया था:
- सार या इंटरफ़ेस वर्गों का उपयोग करने में असमर्थता;
- उपवर्ग में असमर्थता;
- आवेदन भर में उच्च युग्मन (संशोधित करने के लिए मुश्किल);
- परीक्षण करने में कठिनाई (यूनिट परीक्षणों में नकली / नकली नहीं हो सकती);
- उत्परिवर्तनीय स्थिति के मामले में समानांतर करने के लिए मुश्किल (व्यापक लॉकिंग की आवश्यकता होती है);
और मेरे अपने जोड़ें:
- अस्पष्ट या असहनीय आजीवन अनुबंध Android (या अधिकांश अन्य) विकास के लिए अनुपयुक्त;