6

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

एप्लिकेशन के भीतर एक गतिविधि Hashtable<Integer, Question> में प्रश्नों की एक श्रृंखला संग्रहीत करती है, जहां प्रश्न एक छोटा वर्ग है जिसमें दो और दो स्ट्रिंग हैं। मूल रूप से लिखा गया है, गतिविधि प्रत्येक onCreate() पर किसी सर्वर से प्रश्न डाउनलोड करती है, इसलिए मैं कुछ अनावश्यक डाउनलोड को रोकने के लिए onSaveInstanceState() लागू करना चाहता था। onSaveInstanceState()putSerializable() का उपयोग कर बंडल में हैशटेबल बचाता है।

@Override 
protected void onSaveInstanceState(Bundle outState) { 
    super.onSaveInstanceState(outState); 
      // mQuestions is a member variable of 
      // type Hashtable<Integer, Question> 
    if (mQuestions != null && mQuestions.size() > 0) { 
     outState.putSerializable(SAVED_QUESTIONS, mQuestions); 
    } 
} 

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

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

+0

"onSaveInstanceState() बंडल में Hashtable putSerializable() का उपयोग बचाता है।" - उदाहरण के लिए अपने डेटा मॉडल मत डालें। अपने डेटा मॉडल को फ़ाइल या डेटाबेस में रखें। इस तरह आप "अनावश्यक डाउनलोड को रोकें"। "केवल इतना पता था कि जब मैं एमुलेटर की होम कुंजी दबाता था और ऐप चुपचाप दबाता था, तो कोई लॉगकैट आउटपुट के साथ अदृश्य रूप से दुर्घटनाग्रस्त हो गया।" - और इस चुप, अदृश्य दुर्घटना का आपका सबूत है ... क्या, बिल्कुल? – CommonsWare

+0

@ कॉमन्सवेयर: एपलीप्स में एक पॉपअप विंडो डिबग परिप्रेक्ष्य खोलने के लिए कह रही है क्योंकि लॉन्च निलंबित कर दिया गया था। इस तरह मैं जानता था कि यह दुर्घटनाग्रस्त हो गया। मैंने प्रश्न पार्ससेलबल बनाने के लिए कोड पर टिप्पणी की है, और एक कोशिश (कई में से) पर, यह लॉग इन त्रुटियों के साथ मजबूर हो गया है, लेकिन यह सवाल पोस्ट करने से पहले ऐसा नहीं हुआ था। – erichamion

+0

हां, डेटा वास्तव में एक फ़ाइल में सहेजा जाना चाहिए, लेकिन यह वह नहीं है जिसे मैं करने की कोशिश कर रहा था। मैं एक उत्पादन ऐप पर काम नहीं कर रहा हूं (यहां तक ​​कि व्यक्तिगत, शौक के उपयोग के लिए)। मैं 24 घंटे की पुस्तक में _Sam के अपने आप को एंड्रॉइड एप्लिकेशन डेवलपमेंट के माध्यम से बनाए गए डेमो ऐप को संशोधित कर रहा था। यहां तक ​​कि एक प्रारंभिक पुस्तक के लिए, यह कुछ बहुत ही बुनियादी विषयों को छोड़ना प्रतीत होता है। मैं देखना चाहता था कि कैसे SaveInstanceState() काम करता है। मुझे लगता है कि मेरे पास अब इसके मैकेनिक्स हैं, अगर नहीं और कब इसका सबसे अच्छा उपयोग किया जाए। – erichamion

उत्तर

1

का हवाला देते हुए स्टीव मोसली

ध्यान दें कि यह onSaveInstanceState और onRestoreInstanceState उपयोग करने के लिए, http://developer.android.com/reference/android/app/Activity.html में गतिविधि राज्यों पर दस्तावेज़ के अनुसार नहीं सुरक्षित है।

दस्तावेज़ राज्यों ('गतिविधि जीवनचक्र' अनुभाग में):

ध्यान दें कि यह onPause() में लगातार डेटा को बचाने के लिए महत्वपूर्ण है बजाय onSaveInstanceState(Bundle) की क्योंकि बाद में नहीं जीवन चक्र का हिस्सा है कॉलबैक, इसलिए नहीं होगा, जैसा कि प्रत्येक प्रलेखन में वर्णित है।

दूसरे शब्दों में, डाल अपने को बचाने/onPause() और onResume() बजाय में कोड को बहाल!

+0

यह मूल प्रश्न पर एक टिप्पणी के रूप में अधिक उपयुक्त होगा, क्योंकि यह प्रश्न के उत्तर के रूप में उत्तर नहीं दिया गया है: "... ऐप क्रैश केवल होम दबाए जाने पर और स्क्रीन अभिविन्यास परिवर्तन पर क्यों नहीं?" – glorifiedHacker

2

जहां तक ​​मैं समझता हूं कि एंड्रॉइड एक इंस्टेंस स्थिति को क्रमबद्ध नहीं करता है जब कॉन्फ़िगरेशन परिवर्तन के बाद गतिविधि को पुन: प्रयास किया जाता है। यही कारण है कि आपका कोड काम करता है। स्थाई वस्तुओं को केवल पार्सल करने योग्य होने की आवश्यकता नहीं है क्योंकि वे केवल स्मृति में मौजूद हैं।

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

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

किसी भी समय प्रक्रिया समाप्त हो सकती है ताकि आप कुछ कार्यान्वयन विवरणों पर भरोसा न करें। बस उदाहरण के लिए राज्य पार्सलबल या serializable बनाओ और आप इस समस्या का फिर से सामना नहीं करेंगे।

+0

हालांकि मैंने इसे स्वयं की पुष्टि नहीं की है, लेकिन यह जवाब मुझे समझ में आता है (जब चरम स्मृति में स्थिर रहते हैं तो कॉन्फ़िगरेशन परिवर्तन के लिए कुछ क्रमबद्ध क्यों करें)। यह अब तक का एकमात्र उत्तर है कि मूल प्रश्न को संबोधित करने के प्रयासों को एरिचैमियन द्वारा पोस्ट किया गया है। इस प्रकार मैं इस जवाब के लिए बक्षीस दे रहा हूं। – glorifiedHacker

0

ऐप क्रैश नहीं हुआ। जब उपयोगकर्ता ने होम कुंजी पर क्लिक किया तो यह बस बंद हो गया था। यही कारण है कि LogCat के लिए कोई आउटपुट नहीं था।

इसकी पुष्टि करने के लिए Activity.onDestroy() में ब्रेकपॉइंट सेट करें। यदि मैं सही हूं तो Destroy() को कॉल किया जाएगा, लेकिन SaveInstanceState() पर नहीं होगा, क्योंकि SaveInstanceState() को केवल तब कहा जाता है जब ऐप पृष्ठभूमि स्थिति में रखा जाता है, जब यह बंद हो जाता है।

यदि आपको शटडाउन पर ऐप स्थिति को सहेजने की आवश्यकता है, तो कोड को Destroy() पर रखें और इसे बंडल से अधिक लगातार बनाए रखें।

बैरी