मैंने अब महीनों तक इस समस्या की जांच की, इसके विभिन्न समाधानों के साथ आया, जिससे मैं खुश नहीं हूं क्योंकि वे सभी बड़े पैमाने पर हैक हैं। मुझे अभी भी विश्वास नहीं हो रहा है कि डिजाइन में त्रुटिपूर्ण एक वर्ग ने इसे ढांचे में बनाया है और कोई भी इसके बारे में बात नहीं कर रहा है, इसलिए मुझे लगता है कि मुझे कुछ याद आ रहा होगा।
समस्या साथ है AsyncTask
। प्रलेखन के अनुसार यह
"थ्रेड और / या हैंडलर में हेरफेर किए बिना पृष्ठभूमि संचालन करने और UI थ्रेड पर परिणाम प्रकाशित करने की अनुमति देता है।"
उदाहरण तो यह बताता है कि कुछ अनुकरणीय showDialog()
विधि को किस रूप में कहा जाता है onPostExecute()
। यह, हालांकि, पूरी तरह से मेरे लिए Context
विरोधाभास लगता है, क्योंकि एक संवाद को दिखाने के लिए हमेशा एक वैध के संदर्भ की आवश्यकता होती है , और एक AsyncTask को कभी भी संदर्भ वस्तु के लिए एक मजबूत संदर्भ नहीं रखना चाहिए ।
कारण स्पष्ट है: क्या होगा यदि गतिविधि नष्ट हो जाती है जो कार्य को ट्रिगर करती है? यह हर समय हो सकता है, उदाहरण के लिए क्योंकि आपने स्क्रीन को फ़्लिप किया है। यदि यह कार्य उस संदर्भ का संदर्भ देगा, जिसने इसे बनाया है, तो आप न केवल एक बेकार संदर्भ ऑब्जेक्ट पर पकड़ रहे हैं (खिड़की नष्ट हो गई होगी और कोई यूआई इंटरैक्शन अपवाद के साथ विफल हो जाएगा!), आप जोखिम भी पैदा कर सकते हैं! स्मृति रिसाव।
जब तक मेरा तर्क यहाँ त्रुटिपूर्ण नहीं है, तब तक यह अनुवाद करता है: onPostExecute()
पूरी तरह से बेकार है, क्योंकि यूआई थ्रेड पर चलने के लिए इस विधि के लिए क्या अच्छा है यदि आपके पास किसी भी संदर्भ तक पहुंच नहीं है? आप यहां कुछ भी सार्थक नहीं कर सकते।
एक वर्कअराउंड संदर्भ उदाहरणों को AsyncTask पर नहीं, बल्कि एक Handler
उदाहरण के लिए होगा। यह काम करता है: चूंकि एक हैंडलर शिथिल रूप से संदर्भ और कार्य को बांधता है, आप एक रिसाव (दाएं?) को जोखिम में डाले बिना उनके बीच संदेशों का आदान-प्रदान कर सकते हैं। लेकिन इसका मतलब यह होगा कि AsyncTask का आधार, अर्थात आपको हैंडलर से परेशान होने की आवश्यकता नहीं है, गलत है। यह हैंडलर को गाली देने जैसा भी लगता है, क्योंकि आप एक ही धागे पर संदेश भेज रहे हैं और प्राप्त कर रहे हैं (आप इसे यूआई थ्रेड पर बनाते हैं और इसके माध्यम से ऑनपोस्ट एक्स्यूट्यूट () जिसे यूआई थ्रेड पर भी निष्पादित किया जाता है) भेजें।
यह सब बंद करने के लिए, उस समाधान के साथ, आपको अभी भी समस्या है कि जब संदर्भ नष्ट हो जाता है, तो आपके पास कोई रिकॉर्ड नहीं है उन कार्यों का है जो इसे निकाल दिया था। इसका मतलब है कि आपको संदर्भ को फिर से बनाते समय किसी भी कार्य को फिर से शुरू करना होगा, जैसे स्क्रीन ओरिएंटेशन परिवर्तन के बाद। यह धीमा और बेकार है।
मेरा इसका समाधान (जैसा कि Droid-Fu लाइब्रेरी में लागू किया गया है ) है WeakReference
कि यूनिक एप्लिकेशन ऑब्जेक्ट पर घटक नामों से उनके वर्तमान उदाहरणों के लिए मानचित्रण बनाए रखा जाए । जब भी कोई AsyncTask शुरू किया जाता है, तो यह उस मानचित्र में कॉलिंग संदर्भ को रिकॉर्ड करता है, और प्रत्येक कॉलबैक पर, यह उस मैपिंग से वर्तमान संदर्भ उदाहरण प्राप्त करेगा। यह सुनिश्चित करता है कि आप कभी भी बासी संदर्भ उदाहरण का संदर्भ नहीं लेंगे और आपके पास हमेशा कॉलबैक में एक वैध संदर्भ तक पहुंच होगी, ताकि आप वहां सार्थक यूआई काम कर सकें। यह भी लीक नहीं होता है, क्योंकि संदर्भ कमजोर होते हैं और साफ हो जाते हैं जब किसी दिए गए घटक का कोई उदाहरण अब मौजूद नहीं है।
फिर भी, यह एक जटिल बदलाव है और इसे डोराइड-फू पुस्तकालय कक्षाओं में से कुछ को उप-वर्ग करने की आवश्यकता है, जिससे यह एक बहुत ही गहन दृष्टिकोण बन जाता है।
अब मैं बस यह जानना चाहता हूं: क्या मैं केवल सामूहिक रूप से कुछ याद कर रहा हूं या क्या AsyncTask वास्तव में पूरी तरह से त्रुटिपूर्ण है? आपके अनुभव इसके साथ कैसे काम कर रहे हैं? आपने इन समस्या को कैसे हल किया?
आपके सहयोग के लिए धन्यवाद।