2011-08-23 16 views
19

दौरान होता है अगर एंड्रॉयड-support-v4.jar और FragmentActivity (इस बिंदु पर कोई टुकड़े)नहीं बुलाया LoaderCallbacks.onLoadFinished उन्मुखीकरण परिवर्तन AsyncTaskLoader रन

का उपयोग करते हुए मैं एक AsyncTaskLoader जो मैं लोड होना प्रारंभ हो और फिर उन्मुखीकरण जबकि बदल दिया है पृष्ठभूमि धागा अभी भी चल रहा है। मेरे लॉग में मैं प्रतिक्रियाओं को पृष्ठभूमि अनुरोधों के माध्यम से देखता हूं। प्रतिक्रियाएं पूरी होती हैं और मैं लोडफिनिश() पर कॉल करने की अपेक्षा करता हूं, लेकिन यह कभी नहीं होता है।

समस्या निवारण के साधन के रूप में, मैनिफेस्ट में, यदि मैं एंड्रॉइड सेट करता हूं: configChanges = "ओरिएंटेशन" ऑनलोड लोड() को उम्मीद के रूप में कॉल किया जाता है।

मेरी गतिविधि लोडर कॉलबैक लागू करती है। LoaderManager.initLoader() के स्रोत में, मैं देखता हूं कि अगर लोडर पहले से मौजूद है, तो नया कॉलबैक लोडरइन्फो आंतरिक ऑब्जेक्ट क्लास पर सेट है लेकिन मुझे नहीं लगता कि Loader.registerListener() को फिर से कहलाया जाता है। रजिस्टर लिस्टनर को केवल तब कहा जाता है जब LoaderManagerImpl.createAndInstallLoader() को कॉल किया जाता है।

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

क्या कोई मेरी समझ की पुष्टि कर सकता है और समाधान क्या है ताकि लोडफिशिश को अभिविन्यास परिवर्तन के बाद बुलाया जा सके?

+1

एक और समस्या निवारण चरण के रूप में मैंने एक यूआई-कम वर्कर फ्रैगमेंट और सेट रीटेन इंस्टेंस को सत्य में जोड़ा। टुकड़ा लोडर कॉलबैक लागू करता है। फ्रैगमेंट को अभिविन्यास परिवर्तनों के बीच बनाए रखा जाता है लेकिन इसके ऑनलोड लोड() को अभिविन्यास परिवर्तन के बाद कभी नहीं कहा जाता है। – Daddyboy

+7

आप कहां 'initLoader() 'कह रहे हैं? सुनिश्चित करें कि यह 'ऑनक्रेट() 'में है। बीटीडब्लू, आप लोडर लाइफसाइक्ल (लॉगकैट में) के बारे में कुछ डिबगिंग जानकारी प्राप्त करने के लिए 'LoaderManager.enableDebugLogging (true) 'का उपयोग कर सकते हैं। –

उत्तर

34

निकोले ने इस मुद्दे की पहचान की - धन्यवाद।

मैं initLoader fron onResume() पर कॉल कर रहा था। Android दस्तावेज़ राज्यों:

"आप आम तौर पर गतिविधि की OnCreate() विधि, या टुकड़ा के onActivityCreated() विधि के भीतर भीतर एक लोडर आरंभ कर देगा।"

पढ़ें "आम तौर पर" के रूप में थोड़ा अधिक जोरदार से मैंने किया था जब यह विन्यास परिवर्तन जीवन चक्र के साथ काम करने के लिए आता है।

मैंने अपना initLoader कॉल ऑनक्रेट() पर ले जाया और यह मेरी समस्या हल कर दी।

मुझे लगता है कि कारण() है कुछ लोडर और LoaderManagers के बारे में काम शुरू है कि FragmentActivity.onCreate में() LoaderManagers का एक संग्रह LastNonConfigurationInstance से और FragmentActivity.onStart में खींचा जाता है। रीज़्यूम() को उस समय तक प्रक्रिया में पहले से ही प्रक्रिया में रखा जा रहा है। जब लोडर को पहली बार तत्काल आवश्यकता होती है, तो बाहर से बाहर initLoader को कॉल करना() अभी भी काम करता है।

+2

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

+1

मुझे एक ही समस्या थी। लेकिन initLoader को चालू करने के लिए सक्रियता() मेरे लिए काम नहीं किया। लेकिन इसे चालू करने के लिए() किया था! यकीन नहीं है कि क्यों है ... एक अच्छे जवाब के लिए धन्यवाद जिसने बहुत मदद की! – Gober

+0

मुझे भी एक ही समस्या का सामना करना पड़ा। यह परिदृश्य हल हो गया है। लेकिन जब लोडर प्रगति पर है तो उपयोगकर्ता फोन लॉक करता है और गतिविधि में आता है, तो लोडफिशिश को कॉल नहीं किया जाता है। – Meher

2

यह वास्तव में initLoader() पर onCreate() में कॉल करने के लिए कॉल नहीं है जो इसे ठीक कर रहा है। यह getLoaderManager() पर कॉल है। संक्षेप में, क्या होता है कि जब कोई गतिविधि पुनरारंभ होती है, तो यह लोडर के बारे में पहले से ही जानता है। यह जब अपनी गतिविधि onStart() हिट उन्हें पुन: प्रारंभ करने की कोशिश करता है, लेकिन फिर यह FragmentHostCallback.doLoaderStart() * में इस कोड को हिट:

void doLoaderStart() { 
    if (mLoadersStarted) { 
     return; 
    } 
    mLoadersStarted = true; 

    if (mLoaderManager != null) { 
     mLoaderManager.doStart(); 
    } else if (!mCheckedForLoaderManager) { 
     mLoaderManager = getLoaderManager("(root)", mLoadersStarted, false); 
     // WTF: Why aren't we calling doStart() here?! 
    } 
    mCheckedForLoaderManager = true; 
} 

getLoaderManager के बाद से() अभी तक नहीं बुलाया गया था, mLoaderManager रिक्त है। इसलिए यह पहली स्थिति छोड़ देता है और mLoaderManager.doStart() पर कॉल करता है।

आप onCreate() में getLoaderManager() पर कॉल करके बस इसका परीक्षण कर सकते हैं। आपको वहां लोडर को इन्सिट/पुनरारंभ करने की आवश्यकता नहीं है।

यह वास्तव में मेरे लिए एक बग जैसा लगता है।

* यह कोड पथ है भले ही आप टुकड़ों का उपयोग नहीं कर रहे हैं, इसलिए उसमें भ्रमित न हों।

संबंधित मुद्दे