एंड्रॉइड में वैश्विक चर कैसे घोषित करें?


595

मैं एक एप्लिकेशन बना रहा हूं जिसके लिए लॉगिन की आवश्यकता है। मैंने मुख्य और लॉगिन गतिविधि बनाई।

मुख्य गतिविधि onCreateविधि में मैंने निम्नलिखित शर्त जोड़ी:

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    ...

    loadSettings();
    if(strSessionString == null)
    {
        login();
    }
    ...
}

onActivityResultविधि है जो निष्पादित किया जाता है, तो लॉगिन प्रपत्र इस तरह दिखता है समाप्त हो जाता है:

@Override
public void onActivityResult(int requestCode,
                             int resultCode,
                             Intent data)
{
    super.onActivityResult(requestCode, resultCode, data);
    switch(requestCode)
    {
        case(SHOW_SUBACTICITY_LOGIN):
        {
            if(resultCode == Activity.RESULT_OK)
            {

                strSessionString = data.getStringExtra(Login.SESSIONSTRING);
                connectionAvailable = true;
                strUsername = data.getStringExtra(Login.USERNAME);
            }
        }
    }

समस्या यह है कि लॉगिन फ़ॉर्म कभी-कभी दो बार दिखाई देता है ( login()विधि को दो बार कहा जाता है) और यह भी जब फ़ोन कीबोर्ड स्लाइड होता है तो लॉगिन फ़ॉर्म फिर से प्रकट होता है और मुझे लगता है कि समस्या चर है strSessionString

क्या कोई जानता है कि उपयोगकर्ता को पहले से ही प्रमाणीकृत होने के बाद प्रदर्शित होने वाले लॉगिन फॉर्म से बचने के लिए वैरिएबल ग्लोबल को कैसे सेट करना है?


सहेजे गए इंस्टेंस राज्य बंडल quicktips.in/…
दीपक स्वामी

जवाबों:


954

मैंने यह उत्तर '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 (या अधिकांश अन्य) विकास के लिए अनुपयुक्त;

93
थैंक यू सूनिल - इस तरह के जवाब यही कारण हैं कि मुझे स्टैक ओवरफ्लो से बहुत प्यार है। अच्छा काम!
जॉनीलांबाडा

5
किसी के लिए भी कि "अपने घोषणापत्र में एप्लिकेशन टैग में उस वर्ग को कैसे निर्दिष्ट करें", इस लेखन के अनुसार, इस प्रश्न के दो अन्य उत्तर हैं जो यह वर्णन करते हैं कि यह कैसे करना है (एंड्रॉइड का उपयोग करें: नाम), एक द्वारा ईबुप्रोफेन और एक माइक ब्राउन द्वारा।
टायलर कोलियर

9
जल्द ही, आपका उत्तर सही है, लेकिन क्या आप देख सकते हैं कि हमें एंड्रॉइड मेनिफेस्ट फ़ाइल में <application android: name = "। MyApp" ... /> जोड़ना चाहिए?
एंटीकैफे

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

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

153

यह उपवर्ग बनाएँ

public class MyApp extends Application {
  String foo;
}

AndroidManifest.xml में android: name जोड़ें

उदाहरण

<application android:name=".MyApp" 
       android:icon="@drawable/icon" 
       android:label="@string/app_name">

1
उसके लिए धन्यवाद। मैं सोच रहा था कि इसे घोषणा में कैसे घोषित किया जाए
किसी ने

3
इसके लिए मेरे लिए काम करने के लिए मुझे "हटाना" पड़ा। ".मेरीऐप" के भीतर
कोई कहीं

3
बस इसे मुख्य गतिविधि के बाद घोषित करें , अन्यथा यह
sami

11
सिर्फ कहना है, यह मुख्य अनुप्रयोग टैग में है कि पहले से ही वहाँ है ... यह एक दूसरा एक नहीं है :) कठिन तरीका सीखना था।
1

java.lang.IllegalAccessException: access to class is not allowed
रैप्टर

142

आवेदन के लिए एक राज्य रखने के सूनिल तरीके से सुझाव अच्छा है, हालांकि इसका एक कमजोर बिंदु है - ऐसे मामले हैं जब ओएस पूरी आवेदन प्रक्रिया को मारता है। इस पर प्रलेखन है - प्रक्रियाओं और जीवनचक्र

एक मामले पर विचार करें - आपका ऐप पृष्ठभूमि में चला जाता है क्योंकि कोई आपको कॉल कर रहा है (फोन ऐप अभी अग्रभूमि में है)। इस मामले में && कुछ अन्य शर्तों के तहत (उपर्युक्त लिंक की जांच करें कि वे क्या हो सकते हैं) OS आपकी एप्लिकेशन प्रक्रिया को मार सकता है, जिसमें Applicationउपवर्ग उदाहरण भी शामिल है। परिणामस्वरूप राज्य खो जाता है। जब आप बाद में आवेदन पर लौटते हैं, तो ओएस अपनी गतिविधि स्टैक और Applicationउपवर्ग उदाहरण को पुनर्स्थापित करेगा , हालांकि myStateक्षेत्र होगा null

AFAIK, राज्य की सुरक्षा की गारंटी देने का एकमात्र तरीका किसी भी प्रकार की स्थिति का उपयोग करना है, जैसे कि एप्लिकेशन फ़ाइल के लिए एक निजी का उपयोग करना या SharedPrefernces(यह अंततः आंतरिक फाइल सिस्टम में एप्लिकेशन फ़ाइल के लिए एक निजी का उपयोग करता है)।


10
साथ बने रहने के लिए +1 SharedPreferences; मैंने इसे कैसे देखा है। मुझे बचाए गए राज्य के लिए वरीयता प्रणाली का दुरुपयोग करना अजीब लगता है, लेकिन यह इतनी अच्छी तरह से काम करता है कि यह मुद्दा सिर्फ शब्दावली का सवाल बन जाता है।
शेजमिस्टर

1
क्या आप कृपया कोड को पोस्ट कर सकते हैं (या स्पष्टीकरण के लिए एक लिंक प्रदान कर सकते हैं) कि कैसे साझा समस्या का समाधान करने के लिए SharedPreferences का उपयोग किया जाता है, जिसका
कोई

2
प्राथमिकताएँ, डेटाबेस, फ़ाइल क्रमांकन, आदि। प्रत्येक गतिविधि राज्य को बनाए रख सकती है यदि वे onSaveInstanceState का उपयोग करते हैं, लेकिन यह मदद नहीं करेगा यदि उपयोगकर्ता गतिविधि से बाहर निकलता है और जो इसे इतिहास स्टैक से हटा देता है, बल बंद हो जाता है, या उनके डिवाइस को चालू कर देता है। ।
डैरेन हिंडर

1
यह व्यवहार बहुत कष्टप्रद है - यह इतना बुरा नहीं होगा यदि आपके आवेदन के ऑनरिमेट () विधि को बुलाया गया था ताकि आप स्थिति से सुरुचिपूर्ण ढंग से निपट सकें।
डीन वाइल्ड

2
मेरी राय में यह सही उत्तर है। यह गतिविधियों के लिए मौजूदा समान एप्लिकेशन इंस्टेंस पर भरोसा करने के लिए एक बग है। मेरे अनुभव में, जब आप पृष्ठभूमि में होते हैं, तो एंड्रॉइड के लिए पूरी तरह से फाड़ देना और अपनी पूरी प्रक्रिया को फिर से बनाना सामान्य है। बैकग्राउंड होने का मतलब सिर्फ कैमरा आशय, ब्राउज़र आशय या फोन कॉल प्राप्त करना हो सकता है।
जारेड क्ल्स

26

सिर्फ एक नोट ..

जोड़ें:

android:name=".Globals"

या जो भी आपने मौजूदा <application> टैग में अपने उपवर्ग का नाम दिया है । मैं <application>प्रकट में एक और टैग जोड़ने की कोशिश कर रहा था और एक अपवाद मिलेगा।


हाय, गिंबल। मुझे भी यही समस्या थी। मेरे पास अपना खुद का <Application> टैग भी था और जब मैं एक और <Application> टैग जोड़ने की कोशिश करता था तो मुझे आपके (अपवाद संदेश) के समान समस्या थी। लेकिन मैंने वही किया जो आपने उल्लेख किया था, और यह काम नहीं किया। मैं अपने <Application> टैग में android: name = "। GlobalClass" जोड़ता हूं, लेकिन यह काम नहीं करता है। क्या आप पूरी तरह से समझा सकते हैं कि आपने इसे कैसे हल किया ??
सोनहजा

3
अच्छा <प्रकट> <एप्लिकेशन एंड्रॉइड: नाम = "। GlobalData"> </ एप्लिकेशन> </ प्रकट>। खराब <प्रकट> <एप्लिकेशन> </ एप्लिकेशन> <एप्लीकेशन एंड्रॉइड: नाम = "। GlobalData"> </ एप्लिकेशन> </ प्रकट>
गिंबल

13

मुझे पता नहीं चला कि एप्लिकेशन टैग को कैसे निर्दिष्ट किया जाए, लेकिन बहुत सारे Googling के बाद, यह प्रकट फ़ाइल डॉक्स से स्पष्ट हो गया: एप्लिकेशन श्लोक में डिफ़ॉल्ट आइकन और लेबल के अलावा एंड्रॉइड: नाम का उपयोग करें।

Android: नाम एप्लिकेशन के लिए लागू किए गए एप्लिकेशन उपवर्ग का पूरी तरह से योग्य नाम है। जब आवेदन प्रक्रिया शुरू की जाती है, तो यह एप्लिकेशन के किसी भी घटक से पहले इस वर्ग को तुरंत हटा दिया जाता है।

उपवर्ग वैकल्पिक है; अधिकांश अनुप्रयोगों को एक की आवश्यकता नहीं होगी। एक उपवर्ग की अनुपस्थिति में, एंड्रॉइड आधार एप्लिकेशन वर्ग के एक उदाहरण का उपयोग करता है।


13

ऐसी वैश्विक संरचनाओं के साथ देशी स्मृति के संग्रह को सुनिश्चित करने के बारे में क्या?

गतिविधियों में एक onPause/onDestroy()विधि है जिसे विनाश कहा जाता है, लेकिन अनुप्रयोग वर्ग में कोई समकक्ष नहीं है। यह सुनिश्चित करने के लिए क्या तंत्र की सिफारिश की जाती है कि वैश्विक संरचनाएं (विशेष रूप से देशी मेमोरी के संदर्भ वाले) कचरा तब उचित रूप से एकत्र किया जाता है जब आवेदन या तो मार दिया जाता है या कार्य स्टैक को पृष्ठभूमि में रखा जाता है?


1
स्पष्ट समाधान देशी संसाधनों के लिए जिम्मेदार आपकी वस्तुओं के लिए क्लोजेबल इंटरफ़ेस को लागू करना है और यह सुनिश्चित करना है कि वे एक प्रयास के साथ-साथ संसाधनों के बयान या कुछ और द्वारा प्रबंधित किए जाते हैं। सबसे खराब स्थिति आप हमेशा एक ऑब्जेक्ट फाइनलिज़र का उपयोग कर सकते हैं।
जल्द ही

5

बस आपको नीचे दिए गए एप्लिकेशन नाम को परिभाषित करना होगा जो काम करेगा:

<application
  android:name="ApplicationName" android:icon="@drawable/icon">
</application>

4

जैसे ऊपर चर्चा की गई थी कि OS किसी भी अधिसूचना के बिना आवेदन को मार सकता है (कोई onDestroy घटना नहीं है) इसलिए इन वैश्विक चर को बचाने का कोई तरीका नहीं है।

SharedPreferences एक समाधान हो सकता है EXCEPT आपके पास COMPLEX STRUCTURED चर है (मेरे मामले में मेरे पास आईडी को संग्रहीत करने के लिए पूर्णांक सरणी थी जो उपयोगकर्ता पहले ही संभाल चुका है)। SharedPreferences के साथ समस्या यह है कि इन संरचनाओं को हर बार आवश्यक मानों को संग्रहीत और पुनर्प्राप्त करना मुश्किल है।

मेरे मामले में मेरे पास एक पृष्ठभूमि सेवा थी, इसलिए मैं इस चर को वहां स्थानांतरित कर सकता था और क्योंकि सेवा में onDestroy घटना है, मैं उन मूल्यों को आसानी से बचा सकता था।


onDestroy () एक सेवा के लिए भी बुलाया जाने की गारंटी नहीं है।
ओपनजीएल ईएस

हां, यह हो सकता है लेकिन केवल गंभीर स्थितियों के मामले में।
Adorjan Princz

4

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

तो सही तरीका खोजें, और कोई सबसे अच्छा तरीका नहीं है।


3

इस तरह की स्थिति को संग्रहीत करने के लिए आपके पास एक स्थिर क्षेत्र हो सकता है। या इसे संसाधन बंडल में रखें और वहां से ऑनक्रिएट (बंडल सेवइन्स्टांसस्टेट) पर पुनर्स्थापित करें। बस सुनिश्चित करें कि आप पूरी तरह से समझते हैं कि एंड्रॉइड ऐप प्रबंधित जीवनचक्र (जैसे कि क्यों लॉगिन) को कीबोर्ड ओरिएंटेशन परिवर्तन कहा जाता है।


2

DO N'T<application> , मैनिफ़ेस्ट फ़ाइल में किसी अन्य टैग का उपयोग करें । बस मौजूदा <application>टैग में एक परिवर्तन करें , इस पंक्ति को जोड़ें android:name=".ApplicationName"जहाँ, ApplicationNameआपके उपवर्ग का नाम होगा (वैश्विक स्टोर करने के लिए उपयोग करें), जिसे आप बनाने जा रहे हैं।

इसलिए, अंत में प्रकट फ़ाइल में आपका एक और केवल <application> टैग इस तरह दिखना चाहिए: -

<application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/Theme.AppCompat.NoActionBar"
        android:name=".ApplicationName"
        >

1

आप Intents, Sqlite, या Shared Preferences का उपयोग कर सकते हैं। जब मीडिया स्टोरेज की बात आती है, तो डॉक्यूमेंट, फोटो और वीडियो की तरह, आप इसके बजाय नई फाइल बना सकते हैं।


1

आप दो तरीकों का उपयोग करके ऐसा कर सकते हैं:

  1. अनुप्रयोग वर्ग का उपयोग करना
  2. साझा वरीयताएँ का उपयोग करना

  3. अनुप्रयोग वर्ग का उपयोग करना

उदाहरण:

class SessionManager extends Application{

  String sessionKey;

  setSessionKey(String key){
    this.sessionKey=key;
  }

  String getSessisonKey(){
    return this.sessionKey;
  }
}

आप नीचे दिए गए अनुसार अपने MainActivity में लॉगिन को लागू करने के लिए ऊपर की कक्षा का उपयोग कर सकते हैं। कोड कुछ इस तरह दिखेगा:

@override 
public void onCreate (Bundle savedInstanceState){
  // you will this key when first time login is successful.
  SessionManager session= (SessionManager)getApplicationContext();
  String key=getSessisonKey.getKey();
  //Use this key to identify whether session is alive or not.
}

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

  1. साझा प्राथमिकताओं का उपयोग करना।

    String MYPREF="com.your.application.session"
    
    SharedPreferences pref= context.getSharedPreferences(MyPREF,MODE_PRIVATE);
    
    //Insert key as below:
    
    Editot editor= pref.edit();
    
    editor.putString("key","value");
    
    editor.commit();
    
    //Get key as below.
    
    SharedPreferences sharedPref = getActivity().getPreferences(Context.MODE_PRIVATE);
    
    String key= getResources().getString("key");

0

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


0

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

विवरण के लिए यह उदाहरण देखें

यदि आप इतना अधिक कर सकते हैं तो मैनुअल काम क्यों करें?


0
class GlobaleVariableDemo extends Application {

    private String myGlobalState;

    public String getGlobalState(){
     return myGlobalState;
    }
    public void setGlobalState(String s){
     myGlobalState = s;
    }
}

class Demo extends Activity {

@Override
public void onCreate(Bundle b){
    ...
    GlobaleVariableDemo appState = ((GlobaleVariableDemo)getApplicationContext());
    String state = appState.getGlobalState();
    ...
    }
}

0

आप एक वर्ग बना सकते हैं जो कक्षा का विस्तार करता है Applicationऔर फिर अपने चर को उस वर्ग के क्षेत्र के रूप में घोषित करता है और इसके लिए गटर विधि प्रदान करता है।

public class MyApplication extends Application {
    private String str = "My String";

    synchronized public String getMyString {
        return str;
    }
}

और फिर उस चर को अपनी गतिविधि में एक्सेस करने के लिए, इसका उपयोग करें:

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