लोडर मैनजर में initLoader और restartLoader के बीच अंतर


129

मैं initLoaderऔर के restartLoaderकार्यों के बीच के अंतर के बारे में पूरी तरह से हार गया हूँ LoaderManager:

  • उन दोनों के हस्ताक्षर एक ही हैं।
  • restartLoader लोडर भी बनाता है, अगर यह मौजूद नहीं है ("एक नया शुरू करता है या इस प्रबंधक में एक मौजूदा लोडर को पुनरारंभ करता है")।

क्या दोनों विधियों के बीच कुछ संबंध है? कॉलिंग restartLoaderहमेशा कॉल करता है initLoader? क्या मैं restartLoaderबिना बुलाए आ सकता हूं initLoader? क्या initLoaderडेटा को ताज़ा करने के लिए दो बार कॉल करना सुरक्षित है ? मुझे दोनों में से एक का उपयोग कब और क्यों करना चाहिए ?

जवाबों:


202

इस प्रश्न का उत्तर देने के लिए आपको LoaderManagerकोड में खुदाई करने की आवश्यकता है । जबकि LoaderManager के लिए प्रलेखन ही पर्याप्त नहीं है (या यह सवाल नहीं होगा), LoaderManagerImpl के लिए प्रलेखन, अमूर्त LoaderManager के एक उपवर्ग, बहुत अधिक ज्ञानवर्धक है।

initLoader

लोडर के साथ एक विशेष आईडी को इनिशियलाइज़ करने के लिए कॉल करें। यदि इस आईडी में पहले से लोडर जुड़ा हुआ है, तो इसे अपरिवर्तित छोड़ दिया जाता है और किसी भी पिछले कॉलबैक को नए प्रदान किए गए लोगों के साथ बदल दिया जाता है। यदि वर्तमान में आईडी के लिए कोई लोडर नहीं है, तो एक नया बनाया और शुरू किया गया है।

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

restartLoader

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

[...] इस फ़ंक्शन को कॉल करने के बाद, इस आईडी से जुड़े किसी भी पिछले लोडर को अमान्य माना जाएगा, और आपको उनसे कोई और डेटा अपडेट नहीं मिलेगा।

मूल रूप से दो मामले हैं:

  1. आईडी के साथ लोडर मौजूद नहीं है: दोनों विधियाँ एक नया लोडर बनाएंगी ताकि वहाँ कोई अंतर न हो
  2. आईडी के साथ लोडर पहले से मौजूद है: initLoaderकेवल एक पैरामीटर के रूप में पारित कॉलबैक को बदल देगा, लेकिन लोडर को रद्द या बंद नहीं करेगा। के लिए एक CursorLoaderहै कि साधन कर्सर रहता खुले और सक्रिय (है कि अगर पहले मामला था initLoaderकॉल)। `पुनः आरंभकर्ता, दूसरी ओर, लोडर को रद्द, रोक देगा और नष्ट कर देगा (और कर्सर की तरह अंतर्निहित डेटा स्रोत को बंद कर देगा) और एक नया लोडर बनाएगा (जो एक नया कर्सर भी बनाएगा और लोडर होने पर क्वेरी को फिर से चलाएगा। एक CursorLoader)।

यहाँ दोनों विधियों के लिए सरलीकृत कोड दिया गया है:

initLoader

LoaderInfo info = mLoaders.get(id);
if (info == null) {
    // Loader doesn't already exist -> create new one
    info = createAndInstallLoader(id, args, LoaderManager.LoaderCallbacks<Object>)callback);
} else {
   // Loader exists -> only replace callbacks   
   info.mCallbacks = (LoaderManager.LoaderCallbacks<Object>)callback;
}

restartLoader

LoaderInfo info = mLoaders.get(id);
if (info != null) {
    LoaderInfo inactive = mInactiveLoaders.get(id);
    if (inactive != null) {
        // does a lot of stuff to deal with already inactive loaders
    } else {
        // Keep track of the previous instance of this loader so we can destroy
        // it when the new one completes.
        info.mLoader.abandon();
        mInactiveLoaders.put(id, info);
    }
}
info = createAndInstallLoader(id, args,  (LoaderManager.LoaderCallbacks<Object>)callback);

जैसा कि हम देख सकते हैं कि लोडर मौजूद नहीं है (जानकारी == अशक्त) दोनों विधियाँ एक नया लोडर (जानकारी = createAndInstallLoader (...)) बनाएंगी। यदि लोडर पहले से ही मौजूद है तो initLoaderकेवल कॉलबैक (info.mCallbacks = ...) को बदल देता है जबकि restartLoaderपुराने लोडर को निष्क्रिय कर देता है (जब नया लोडर अपना काम पूरा कर लेता है) तब यह नष्ट हो जाता है और फिर एक नया बनाता है।

इस प्रकार कहा कि अब यह स्पष्ट है कि कब उपयोग करना है initLoaderऔर कब उपयोग करना है restartLoaderऔर यह दो तरीकों के लिए क्यों समझ में आता है। initLoaderयह सुनिश्चित करने के लिए उपयोग किया जाता है कि एक इनिशियलाइज्ड लोडर है। यदि कोई भी मौजूद नहीं है तो एक नया बनाया जाता है, यदि कोई पहले से मौजूद है तो उसका पुनः उपयोग किया जाता है। हम हमेशा इस तरीके का उपयोग करते हैं UNLESS के लिए हमें एक नए लोडर की आवश्यकता होती है क्योंकि चलाने के लिए क्वेरी बदल गई है (अंतर्निहित डेटा नहीं है, लेकिन CursorLoader के लिए SQL कथन की तरह वास्तविक क्वेरी), जिस स्थिति में हम कॉल करेंगे restartLoader

गतिविधि / टुकड़ा जीवन चक्र से एक का उपयोग करने का निर्णय या अन्य विधि के साथ कोई संबंध नहीं है (और एक एक शॉट ध्वज का उपयोग कर कॉल का ट्रैक रखने के रूप में साइमन सुझाव की आवश्यकता नहीं है)! यह निर्णय पूरी तरह से एक नए लोडर के लिए "आवश्यकता" पर आधारित है। यदि हम उसी क्वेरी को चलाना चाहते हैं जिसका हम उपयोग करते हैं initLoader, यदि हम एक अलग क्वेरी चलाना चाहते हैं जिसका हम उपयोग करते हैं restartLoader

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

लोड किए गए डेटा और उस डेटा को लोड करने के लिए "क्वेरी" के बीच अंतर को समझना बहुत महत्वपूर्ण है। चलो मान लेते हैं कि हम आदेशों के लिए एक तालिका को क्वेरी करते हुए CursorLoader का उपयोग करते हैं। यदि उस तालिका में एक नया आदेश जोड़ा जाता है तो CursorLoader UI को अपडेट करने और नए आदेश ( restartLoaderइस मामले में उपयोग करने की आवश्यकता नहीं) को सूचित करने के लिए onContentChanged () का उपयोग करता है । यदि हम केवल खुले आदेशों को प्रदर्शित करना चाहते हैं, तो हमें एक नई क्वेरी की आवश्यकता है और हम नई क्वेरी restartLoaderको दर्शाते हुए एक नया CursorLoader वापस करने के लिए उपयोग करेंगे ।


क्या दोनों विधियों के बीच कुछ संबंध है?

वे एक नया लोडर बनाने के लिए कोड साझा करते हैं, लेकिन वे अलग-अलग चीजें करते हैं जब एक लोडर पहले से मौजूद है।

कॉलिंग restartLoaderहमेशा कॉल करता है initLoader?

नहीं, ऐसा कभी नहीं होता।

क्या मैं restartLoaderबिना बुलाए आ सकता हूं initLoader?

हाँ।

क्या initLoaderडेटा को ताज़ा करने के लिए दो बार कॉल करना सुरक्षित है ?

यह initLoaderदो बार कॉल करने के लिए सुरक्षित है लेकिन कोई डेटा ताज़ा नहीं किया जाएगा।

मुझे दोनों में से एक का उपयोग कब और क्यों करना चाहिए ?


ऊपर मेरे स्पष्टीकरण के बाद यह (उम्मीद) स्पष्ट होना चाहिए।

कॉन्फ़िगरेशन बदलता है

एक LoaderManager कॉन्फ़िगरेशन परिवर्तन (अभिविन्यास परिवर्तन सहित) में अपनी स्थिति को बनाए रखता है, इसलिए आपको लगता है कि हमारे लिए ऐसा करने के लिए कुछ भी नहीं बचा है। फिर से विचार करना...

सबसे पहले, एक LoaderManager कॉलबैक को बनाए नहीं रखता है, इसलिए यदि आप कुछ भी नहीं करते हैं तो आपको अपने कॉलबैक विधियों जैसे onLoadFinished()और जैसे कॉल प्राप्त नहीं होंगे और यह आपके ऐप को बहुत ही आसानी से तोड़ देगा।

इसलिए हमें initLoaderकॉलबैक विधियों (ए restartLoader, निश्चित रूप से, बहुत संभव है) को पुनर्स्थापित करने के लिए कम से कम कॉल करना होगा । प्रलेखन कहता है:

यदि कॉल के बिंदु पर कॉल करने वाला चालू स्थिति में है, और अनुरोधित लोडर पहले से मौजूद है और उसने अपना डेटा जेनरेट किया है, तो कॉलबैक onLoadFinished(Loader, D)को तुरंत (इस फ़ंक्शन के अंदर) कहा जाएगा [...]।

इसका मतलब है कि यदि हम initLoaderअभिविन्यास परिवर्तन के बाद कॉल करते हैं, तो हमें onLoadFinishedतुरंत कॉल मिलेगा क्योंकि डेटा पहले से ही लोड है (यह मानते हुए कि परिवर्तन से पहले मामला था)। जबकि यह सीधे लगता है कि यह मुश्किल हो सकता है (हम सभी एंड्रॉइड को प्यार नहीं करते ...)।

हमें दो मामलों में अंतर करना होगा:

  1. हैंडल कॉन्फ़िगरेशन स्वयं बदल जाता है: यह Fragments के लिए मामला है जो setRetainInstance (सही) या गतिविधि के android:configChangesलिए प्रकट टैग के अनुसार गतिविधि का उपयोग करता है। इन घटकों को एक स्क्रीन घुमाव के बाद ऑनक्रीट कॉल प्राप्त नहीं होगी, इसलिए initLoader/restartLoaderकॉलबैक विधि (जैसे onActivityCreated(Bundle)) में कॉल करने के लिए ध्यान रखें । लोडर (ओं) को शुरू करने में सक्षम होने के लिए, लोडर आईडी को संग्रहीत करने की आवश्यकता होती है (जैसे एक सूची में)। क्योंकि घटक को कॉन्फ़िगरेशन परिवर्तनों के दौरान बनाए रखा जाता है, हम मौजूदा लोडर आईडी और कॉल पर लूप कर सकते हैं initLoader(loaderid, ...)
  2. कॉन्फ़िगरेशन परिवर्तन को स्वयं हैंडल नहीं करता है: इस स्थिति में लोडर ऑनक्रिएट में आरंभीकृत किए जा सकते हैं, लेकिन हमें लोडर आईडी को मैन्युअल रूप से बनाए रखने की आवश्यकता है या हम आवश्यक initLoader / restartLoader कॉल करने में सक्षम नहीं होंगे। अगर आईडी को एक ArrayList में संग्रहीत किया जाता है, तो हम
    outState.putIntegerArrayList(loaderIdsKey, loaderIdsArray)onSaveInstanceState में करेंगे और आईडी को onCreate में पुनर्स्थापित करेंगे: loaderIdsArray = savedInstanceState.getIntegerArrayList(loaderIdsKey)इससे पहले कि हम initLoader call (s) करें।

: +1: एक अंतिम बिंदु। यदि आप उपयोग करते हैं initLoader(और सभी कॉलबैक समाप्त हो गए हैं, तो लोडर बेकार है) एक रोटेशन के बाद आपको onLoadFinishedकॉलबैक नहीं मिलेगा लेकिन यदि आप restartLoaderअपनी इच्छा का उपयोग करते हैं?
१३:४१ पर ब्लंडेल

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

6
आह, निश्चित रूप से आपके उत्तर और @ एलेक्सलॉकवुड का संयोजन पूरी तस्वीर देता है। मुझे लगता है कि दूसरों के लिए जवाब है, initLoader का उपयोग करें यदि आपकी क्वेरी स्थिर है और यदि आप क्वेरी बदलना चाहते हैं तो पुनः आरंभ करें
Blundell

1
यह अच्छी तरह से सम्मन: "initLoader का उपयोग करें यदि आपकी क्वेरी स्थिर है और यदि आप क्वेरी को बदलना चाहते हैं तो पुनः आरंभ करें"
Emanuel Moecklin

1
@Mhd। तहवी आप कॉलबैक नहीं बदल रहे हैं, आप उन्हें केवल उन्हीं स्थानों पर सेट करें जहाँ उन्हें जाना चाहिए। एक स्क्रीन रोटेशन के बाद उन्हें फिर से सेट करने की आवश्यकता है क्योंकि एंड्रॉइड मेमोरी लीक को रोकने के लिए उन्हें आसपास नहीं रखेगा। जब तक आप सही काम करना चाहते हैं, तब तक आप उन्हें सेट करने के लिए स्वतंत्र हैं।
इमानुएल मोएक्लिन

46

initLoaderजब लोडर पहले से ही बनाया गया है तब कॉल करना (यह आमतौर पर कॉन्फ़िगरेशन परिवर्तन के बाद होता है, उदाहरण के लिए) लोडर प्रबंधक को लोडर के सबसे हाल के डेटा को onLoadFinishedतुरंत वितरित करने के लिए कहता है । यदि लोडर पहले से ही नहीं बनाया गया है (जब गतिविधि / टुकड़ा पहले लॉन्च होता है, उदाहरण के लिए) तो लोडर initLoaderप्रबंधक को onCreateLoaderनए लोडर बनाने के लिए कॉल करने के लिए कहता है ।

कॉलिंग restartLoaderएक पहले से मौजूद लोडर को नष्ट कर देती है (साथ ही इससे जुड़े किसी भी मौजूदा डेटा को) और onCreateLoaderलोडर मैनेजर को नए लोडर बनाने के लिए कॉल करने और एक नया लोड शुरू करने के लिए कहता है ।


प्रलेखन इस बारे में बहुत स्पष्ट है:

  • initLoaderसुनिश्चित करता है कि एक लोडर आरंभीकृत और सक्रिय है। यदि लोडर पहले से मौजूद नहीं है, तो एक बनाया जाता है और (यदि गतिविधि / टुकड़ा वर्तमान में शुरू होता है) लोडर शुरू होता है। अन्यथा अंतिम निर्मित लोडर का फिर से उपयोग किया जाता है।

  • restartLoaderएक नया शुरू करता है या इस प्रबंधक में एक मौजूदा लोडर को पुनरारंभ करता है, इसे कॉलबैक को पंजीकृत करता है, और (यदि गतिविधि / टुकड़ा वर्तमान में शुरू हो गया है) इसे लोड करना शुरू कर देता है। यदि उसी आईडी के साथ एक लोडर को पहले ही शुरू कर दिया गया है तो नया लोडर अपना काम पूरा करने पर स्वचालित रूप से नष्ट हो जाएगा। पुराने लोडर को नष्ट करने से पहले कॉलबैक दिया जाएगा।


@TomanMoney मैंने बताया कि मेरे उत्तर में इसका क्या अर्थ है। आप किस भाग के बारे में भ्रमित हैं?
एलेक्स लॉकवुड

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

3
@TomanMoney आमतौर पर जब आप गतिविधि / विखंडन शुरू करते हैं तो / initLoader()में उपयोग करते हैं । इस तरह, जब उपयोगकर्ता पहली बार एक गतिविधि खोलता है, लोडर पहली बार बनाया जाएगा ... लेकिन किसी भी बाद के कॉन्फ़िगरेशन परिवर्तन पर जहां संपूर्ण गतिविधि / खंड को नष्ट किया जाना चाहिए, निम्नलिखित कॉल केवल पुराने के बजाय पुराने को वापस कर देगा एक नया निर्माण। आमतौर पर आप तब इस्तेमाल करते हैं जब आपको 's क्वेरी' बदलने की जरूरत होती है (यानी आप फ़िल्टर किए गए / सॉर्ट किए गए डेटा, आदि को प्राप्त करना चाहते हैं)। onCreate()onActivityCreated()initLoader()LoaderrestartLoader()Loader
एलेक्स लॉकवुड

4
मैं अभी भी दोनों विधियों के एपीआई निर्णय के बारे में उलझन में हूं, क्योंकि उनके पास एक ही हस्ताक्षर है। API हर बार एक "startLoader () पद्धति क्यों नहीं बना सकता जो" सही काम "करती है? मुझे लगता है कि यह वह हिस्सा है जो बहुत सारे लोगों को भ्रमित करता है।
टॉम aMoney

1
@TomanMoney यहां प्रलेखन कहता है: developer.android.com/guide/compords/loaders.html । "वे स्वचालित रूप से अंतिम लोडर के कर्सर को फिर से कनेक्ट करते हैं जब कॉन्फ़िगरेशन परिवर्तन के बाद फिर से बनाया जाता है। इस प्रकार, उन्हें अपने डेटा को फिर से क्वेरी करने की आवश्यकता नहीं है।"
इगोरगानापोलस्की

16

मैंने हाल ही में कई लोडर प्रबंधकों और स्क्रीन ओरिएंटेशन परिवर्तनों के साथ एक समस्या को हिट किया है और यह कहना चाहूंगा कि बहुत सारे परीक्षण और त्रुटि के बाद, निम्नलिखित पैटर्न मेरे लिए एक्टिविटीज़ और फ्रेग्मेंट्स दोनों में काम करता है:

onCreate: call initLoader(s)
          set a one-shot flag
onResume: call restartLoader (or later, as applicable) if the one-shot is not set.
          unset the one-shot in either case.

(दूसरे शब्दों में, कुछ झंडा ताकि सेट initLoader है हमेशा एक बार और कि restartLoader पर चलाया जाता है चलाने के 2 और बाद में पास के माध्यम से onResume )

साथ ही, अपने प्रत्येक लोडर के लिए एक गतिविधि के भीतर अलग-अलग आईडी निर्दिष्ट करना याद रखें (जो कि उस गतिविधि के भीतर टुकड़े के साथ एक समस्या हो सकती है यदि आप अपनी संख्या के साथ सावधान नहीं हैं)


मैं केवल initLoader का उपयोग करने की कोशिश की .... प्रभावी ढंग से काम नहीं कर रहा था।

की कोशिश की initLoader पर onCreate अशक्त आर्ग के साथ (डॉक्स का कहना है कि यह ठीक है) और restartLoader में (मान्य आर्ग के साथ) onResume .... डॉक्स गलत हैं और initLoader एक nullpointer अपवाद फेंकता है।

केवल पुनरारंभ किए जाने की कोशिश की गई ... थोड़ी देर के लिए काम करती है, लेकिन 5 वीं या 6 ठी स्क्रीन पर फिर से उन्मुख होता है।

OnResume में initLoader की कोशिश की ; थोड़ी देर के लिए फिर से काम करता है और फिर उड़ जाता है। (विशेष रूप से "शुरू नहीं होने पर कॉल किया जाता है:" ... त्रुटि)

निम्नलिखित की कोशिश की: (एक कवर वर्ग से अंश जिसे लोडर आईडी कंस्ट्रक्टर में पारित किया गया है)

/**
 * start or restart the loader (why bother with 2 separate functions ?) (now I know why)
 * 
 * @param manager
 * @param args
 * @deprecated use {@link #restart(LoaderManager, Bundle)} in onResume (as appropriate) and {@link #initialise(LoaderManager, Bundle)} in onCreate 
 */
@Deprecated 
public void start(LoaderManager manager, Bundle args) {
    if (manager.getLoader(this.id) == null) {
        manager.initLoader(this.id, args, this);
    } else {
        manager.restartLoader(this.id, args, this);
    }
}

(जो मैंने स्टैक-ओवरफ्लो में कहीं पाया)

फिर से, इसने कुछ समय के लिए काम किया लेकिन फिर भी सामयिक गड़बड़ को फेंक दिया।


से मैं क्या जबकि डीबगिंग, मुझे लगता है के साथ बचाने / उदाहरण राज्य को बहाल करने के लिए कुछ है कि आवश्यकता है कि है कि वहाँ पता लगा सकते हैं initLoader (/ s) में चलाए जा रहे हैं onCreate जीवन चक्र का हिस्सा अगर वे चक्र के एक स्पिन जीवित रहने के लिए कर रहे हैं । ( शायद मैं गलत हो सकता हूँ।)

प्रबंधकों है कि शुरू नहीं किया जा सकता है जब तक परिणाम एक और प्रबंधक या कार्य से वापस आते हैं के मामले में (यानी। में initialised नहीं किया जा सकता onCreate ), मैं केवल का उपयोग initLoader । (मैं इसमें सही नहीं हो सकता, लेकिन यह काम करने लगता है। ये माध्यमिक लोडर तत्काल उदाहरण-स्थिति का हिस्सा नहीं हैं, इसलिए initLoader का उपयोग करना वास्तव में इस मामले में सही हो सकता है)

जीवन चक्र


आरेखों और डॉक्स को देखते हुए, मैंने सोचा होगा कि InitLoader को OnRestart में OnCreate और restartLoader में जाना चाहिए लेकिन गतिविधियों के लिए कुछ अलग पैटर्न का उपयोग करके Fragments छोड़ देता है और मेरे पास यह जांचने का समय नहीं है कि यह वास्तव में स्थिर है। क्या कोई और टिप्पणी कर सकता है कि क्या उन्हें गतिविधियों के लिए इस पैटर्न के साथ सफलता मिली है?


/ @ साइमन 100% सही है और यह स्वीकृत उत्तर होना चाहिए। मैंने उनके जवाब पर बहुत विश्वास नहीं किया और इस काम को करने के विभिन्न तरीकों को खोजने की कोशिश में कई घंटे बिताए। जैसे ही मैंने initLoader को कॉल किया, onCreate चीजों पर काम करना शुरू कर दिया। तब आपको एक-शॉट फ्लैग की जरूरत होती है, जिसे ऑनस्टार्ट कहते हैं, लेकिन कोई
ऑनक्रिएट

2
"केवल पुनः आरंभ करने की कोशिश की ... थोड़ी देर के लिए काम करता है लेकिन 5 वीं या 6 वीं स्क्रीन पर फिर से उन्मुख होता है।" ऐसा होता है? मैंने बस कोशिश की और स्क्रीन को सौ बार घुमाया और कोई झटका नहीं लगा। आपको किस तरह का अपवाद मिल रहा है?
टॉम मौनी

-1 मैं इस उत्तर के पीछे शोध के प्रयासों की सराहना करता हूं लेकिन अधिकांश परिणाम गलत हैं।
इमानुएल मोएक्लिन

1
@IgorGanapolsky लगभग सब कुछ। यदि आप मेरे उत्तर को पढ़ते हैं और समझते हैं तो आप समझ जाएंगे कि initLoader और restartLoader क्या करते हैं और कब और कौन सा उपयोग करना है और आप यह भी समझेंगे कि साइमन के लगभग सभी निष्कर्ष गलत क्यों हैं। एक टुकड़ा / गतिविधि के जीवन चक्र और निर्णय के बीच कोई संबंध नहीं है जब initLoader / restartLoader का उपयोग करना है (एक कैविटी के साथ मैं कॉन्फ़िगरेशन परिवर्तन के तहत समझाता हूं)। साइमन परीक्षण और त्रुटि से यह निष्कर्ष निकालता है कि जीवन चक्र दो तरीकों को समझने का सुराग है लेकिन ऐसा नहीं है।
इमानुएल मोकेलिन

@IgorGanapolsky मैं अपने जवाब का विज्ञापन करने की कोशिश नहीं कर रहा हूँ। मैं केवल अन्य डेवलपर्स की मदद करने की कोशिश कर रहा हूं और उन्हें अपने स्वयं के ऐप के लिए साइमन के परिणामों का उपयोग करने से रोकता हूं। एक बार जब आप समझ जाते हैं कि दो तरीके क्या हैं, तो यह पूरी तरह से स्पष्ट हो जाता है और लागू करने के लिए सीधे आगे हो जाता है।
इमानुएल मोकेलिन

0

initLoaderयदि लोडर पहले से मौजूद है तो उन्हीं मापदंडों का पुन: उपयोग करेंगे। यदि पुराना डेटा पहले से लोड है, तो भी यह तुरंत वापस आ जाता है, भले ही आप इसे नए मापदंडों के साथ कहें। लोडर को आदर्श रूप से नए डेटा की गतिविधि को स्वचालित रूप से सूचित करना चाहिए। यदि स्क्रीन घुमाया initLoaderजाता है , तो फिर से कॉल किया जाएगा और पुराने डेटा को तुरंत प्रदर्शित किया जाएगा।

restartLoaderजब आप एक पुनः लोड करना चाहते हैं और साथ ही मापदंडों को बदलना चाहते हैं। यदि आप लोडरों का उपयोग करके एक लॉगिन स्क्रीन बनाने के लिए थे, तो आप restartLoaderबटन को क्लिक करने के बाद हर बार कॉल करेंगे । (गलत क्रेडेंशियल्स आदि के कारण बटन को कई बार क्लिक किया जा सकता है)। आप केवल तभी कॉल करेंगे initLoaderजब गतिविधि के सहेजे गए इंस्टेंस राज्य को पुनर्स्थापित करने की स्थिति में स्क्रीन को घुमाया गया था जबकि लॉगिन चालू था।


-1

यदि लोडर पहले से मौजूद है, तो पुनः आरंभक पुराने को बंद / रद्द / नष्ट कर देगा, जबकि initLoader इसे दिए गए कॉलबैक के साथ आरंभ करेगा। मुझे नहीं पता चल पाया है कि इन मामलों में पुरानी कॉलबैक क्या है, लेकिन मुझे लगता है कि वे बस छोड़ दिए जाएंगे।

मैंने http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.0.1_r1/android/app/LoaderManager.jw पर स्कैन किया लेकिन मुझे पता नहीं है कि सटीक क्या है अंतर यह है कि इसके अलावा तरीके अलग-अलग काम करते हैं। तो मैं कहूंगा, पहली बार initLoader का उपयोग करें और निम्नलिखित समय के लिए पुनरारंभ करें, हालांकि मैं निश्चितता के साथ नहीं कह सकता कि उनमें से प्रत्येक वास्तव में क्या करेगा।


और initLoaderइस मामले में क्या करेंगे ?
ओमेगा

-1

पहली लोड पर इनिट लोडर लोडइन्कब्रैकग्राउंड () पद्धति का उपयोग करता है, दूसरी शुरुआत में इसे छोड़ दिया जाएगा। तो, मेरी राय, बेहतर समाधान है:

Loader<?> loa; 
try {
    loa = getLoaderManager().getLoader(0);
} catch (Exception e) {
    loa = null;
}
if (loa == null) {
    getLoaderManager().initLoader(0, null, this);
} else {
    loa.forceLoad();
}

////////////////////////////////////////////////// /////////////////////////

protected SimpleCursorAdapter mAdapter;

private abstract class SimpleCursorAdapterLoader 
    extends AsyncTaskLoader <Cursor> {

    public SimpleCursorAdapterLoader(Context context) {
        super(context);
    }

    @Override
    protected void onStartLoading() {
        if (takeContentChanged() || mAdapter.isEmpty()) {
            forceLoad();
        }
    }

    @Override
    protected void onStopLoading() {
        cancelLoad();
    }

    @Override
    protected void onReset() {
        super.onReset();
        onStopLoading();
    }
}

मैंने इस समाधान को खोजने के लिए कई समय बिताए - पुनः आरंभ करें (...) मेरे मामले में ठीक से काम नहीं किया। एकमात्र बललॉड () कॉलबैक के बिना पिछले लोडिंग थ्रेड को पूरा करने की अनुमति देता है (ताकि आपके पास सभी डीबी लेनदेन ठीक से समाप्त हो जाएंगे) और फिर से नया थ्रेड शुरू होता है। हां, यह कुछ अतिरिक्त समय की मांग करता है, लेकिन अधिक स्थिर है। केवल अंतिम प्रारंभ धागा कॉलबैक ले जाएगा। इस प्रकार, यदि आप अपने db लेनदेन को बाधित करने के साथ परीक्षण करना चाहते हैं - आपका स्वागत है, तो पुनः आरंभ करने की कोशिश करें (...), अन्यथा forceLoad ()। पुनः आरंभकर्ता (...) की एकमात्र सुविधा नए प्रारंभिक डेटा को वितरित करने के लिए है, मेरा मतलब है कि पैरामीटर। और कृपया इस मामले में उपयुक्त फ्रैगमेंट की ऑनडेट () विधि में लोडर को नष्ट करना न भूलें। यह भी ध्यान रखें, कि कुछ समय, जब आपके पास कोई गतिविधि हो और, उन्हें कहने दें, लोडर के साथ 2 टुकड़े प्रत्येक एक समावेशी गतिविधि - आप केवल 2 लोडर प्रबंधकों तक पहुंचेंगे, इसलिए गतिविधि अपने लोडरमैन को फ्रैगमेंट (एस) के साथ साझा करती है, जिसे लोडिंग के दौरान स्क्रीन पर पहले दिखाया गया है। LoaderManager.enableDebugLogging (सत्य) आज़माएँ; प्रत्येक निश्चित मामले में विवरण देखने के लिए।


2
getLoader(0)एक में कॉल लपेटने के लिए -1 try { ... } catch (Exception e) { ... }
एलेक्स लॉकवुड
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.