8

पर मेरी समस्या में तीन समर्थन खंडों की एक गतिविधि शामिल है। एक सामान्य प्रोग्रामेटिक टुकड़ा है (चलिए इसे घर का टुकड़ा कहते हैं)। कॉन्फ़िगरेशन परिवर्तनों के बावजूद एक एसिंक कार्य जारी रखने के लिए, डिवाइस उन्मुख होने पर घर के टुकड़े के शीर्ष पर एक पोर्ट्रेट टुकड़ा जोड़ा जाता है, और एक 'हेडलेस' होता है। बहुत आसान, मैं this nice example से काम कर रहा था।फ्रैगमेंट ए के लिए findFragmentByTag शून्य, अगर सेटगेटन (सत्य) Fragment B

public class HeadlessCustomerDetailFetchFragment extends Fragment{ 
private RequestCustomerDetails mRequest; 
private AsyncFetchCustomerDetails mAsyncFetchCustomerDetails; 

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setRetainInstance(true); 

    mRequest = (RequestCustomerDetails)getActivity(); 
} 

public void startFetching(String scannedBarcode) { 
    if(mAsyncFetchCustomerDetails != null && mAsyncFetchCustomerDetails.getStatus() == AsyncTask.Status.RUNNING) return; 

    if(mAsyncFetchCustomerDetails == null || mAsyncFetchCustomerDetails.getStatus() == AsyncTask.Status.FINISHED) 
     mAsyncFetchCustomerDetails = new AsyncFetchCustomerDetails(getActivity(), mRequest, mPartner, scannedBarcode); 
} 

public void stopFetching() { 
    if(mAsyncFetchCustomerDetails != null && mAsyncFetchCustomerDetails.getStatus() != AsyncTask.Status.RUNNING) return; 
    mAsyncFetchCustomerDetails.cancel(true); 
} 

}

मेरी गतिविधि के onCreate में() मैं बना सकते हैं और यदि आवश्यक हो तो बिना सिर टुकड़ा जोड़ें।

mHeadlessCustomerDetailFetchFragment = (HeadlessCustomerDetailFetchFragment)getSupportFragmentManager() 
      .findFragmentByTag(HeadlessCustomerDetailFetchFragment.class.getSimpleName()); 

if(mHeadlessCustomerDetailFetchFragment == null) { 
     mHeadlessCustomerDetailFetchFragment = HeadlessCustomerDetailFetchFragment.instantiate(this, HeadlessCustomerDetailFetchFragment.class.getName()); 
    getSupportFragmentManager().beginTransaction() 
      .add(mHeadlessCustomerDetailFetchFragment, mHeadlessCustomerDetailFetchFragment.getClass().getSimpleName()) 
      .commit(); 
    getSupportFragmentManager().executePendingTransactions(); 
     id = null; 
    } 

मैं तो (परीक्षण के लिए) एक 6 सेकंड की देरी के बाद (मेरे startFetching() फ़ंक्शन के माध्यम से) एक async कार्य का शुभारंभ चित्र टुकड़ा की onCreateView में शुरू हुआ() कि जोड़ा जाता है जब पोट्रेट पर उन्मुखीकरण परिवर्तन । उन्मुखीकरण परिवर्तन गतिविधि के OnCreate() में पाया जाता है:

if (savedInstanceState == null) { 
    // Do some initial stuff for the home fragment 
} 
else { 
    getSupportFragmentManager().popBackStackImmediate(null, FragmentManager.POP_BACK_STACK_INCLUSIVE); 
    if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) { 
     //Launch portrait fragment 
     FragmentLauncher.launchPortraitFragment(this); 
    } 

जब कार्य समाप्त हो गया है, मैं गतिविधि में लौटने और सक्रिय चित्र टुकड़ा के यूआई अद्यतन करने का प्रयास है, लेकिन टुकड़ा प्रबंधक यह नहीं मिल सकता है, findFragmentByTag() शून्य देता है।

स्पष्ट है:

  • टैग सही है
  • टुकड़ा मिला है अगर मैं डिवाइस बोध, और बदले कहीं और async कार्य शुरू (गतिविधि के onResume दौरान, नहीं है) उदाहरण के लिए।
  • यदि मैं अपने आप को बनाए रखने के लिए हेडलेस टुकड़े नहीं बताता - जिससे इसे पुन: प्रयास न करने का लाभ खो जाता है, तो चित्र खंड भी सही ढंग से पाया जाता है।
  • डीबगिंग मैनेजर में सभी 3 टुकड़े देख सकते हैं यदि हेडलेस एक खुद को बनाए रखने के लिए सेट नहीं है। यदि ऐसा है, तो मैं केवल हेडलेस खंड देख सकता हूं।

शायद एक टुकड़ा को बरकरार रखने से अन्य टुकड़ों को आक्रामक रूप से मार दिया जाता है जो कि बनाए रखा नहीं जाता है या उस प्रभाव से कुछ?

+0

आप सेवा में अपना एसिंक्टस्क क्यों नहीं कर सकते हैं? मेरा मानना ​​है कि यह आपके घूर्णन मुद्दे को समाप्त करता है और यह करने के लिए एक साफ तरीका भी है? – Smashing

+0

मुझे ऐसा भी लगता है - मुझे सेवाओं के बारे में बहुत कुछ पता नहीं है और ऐसा लगता है कि यह एक काम के लिए अधिक है, लेकिन यह मेरा एकमात्र विकल्प हो सकता है - इसमें देखेंगे –

+1

कूलबीन्स। मुझे बताएं क्या आपको किसी भी तरह की मदद की ज़रूरत है। – Smashing

उत्तर

4

समस्या की जड़ यह है कि आप हेडलेस टुकड़े के अंदर गतिविधि के संदर्भ को कैसे बनाए रखते हैं।
यह उपलब्ध कोड से स्पष्ट नहीं है कि आप AsyncTask के पूरा होने के बाद यूआई को कैसे अपडेट करते हैं, मान लें कि आप पहले कोड स्निपेट से mRequest का उपयोग करते हैं। जब आपको नई AsyncTask की आवश्यकता होती है और AsyncTask पूर्ण होने के बाद इस संदर्भ का उपयोग करते हैं तो आप mRequest को कन्स्ट्रक्टर को देते हैं।
यह ठीक है, जब आपके पास गतिविधि के निर्माण के समय और यूआई अपडेट होने पर उस समय के बीच कोई स्क्रीन रोटेशन नहीं होता है। ऐसा इसलिए है क्योंकि आप गतिविधि के संदर्भ का उपयोग करते हैं जो अभी भी सक्रिय है।
यदि आप स्क्रीन घुमाते हैं तो यह ठीक नहीं है। घूर्णन के बाद हर बार आपकी नई गतिविधि होती है। लेकिन mRequest केवल एक बार असाइन किया जाता है जब आप गतिविधि के onCreate() की पहली कॉल में हेडलेस खंड बनाते हैं। तो इसमें गतिविधि के पहले उदाहरण के संदर्भ शामिल हैं जो घूर्णन के बाद सक्रिय नहीं है। आपके मामले में घूर्णन के बाद गतिविधि के 2 उदाहरण हैं: पहला - जिसे mRequest और दूसरा द्वारा संदर्भित किया जाता है - जो दृश्यमान और सक्रिय है।onCreate: Log.i(TAG, "onCreate: this=" + this); के अंदर गतिविधि के संदर्भ को लॉग इन करके आप इसकी पुष्टि कर सकते हैं और गतिविधि की विधि के अंदर जो एसिंक कार्य के बाद यूआई अपडेट करता है: Log.i(TAG, "updating UI: this=" + this);
पहली गतिविधि के अलावा नष्ट राज्य में है। सभी टुकड़े इस गतिविधि से अलग हो जाते हैं और गैर बनाए रखा टुकड़े नष्ट हो जाते हैं। यही कारण है कि findFragmentByTag शून्य वापस आता है।
यदि हेडलेस टुकड़ा खुद को बनाए रखने के लिए सेट नहीं है, तो गतिविधि के onCreate() प्रत्येक कॉल में इसे पुन: प्रयास करता है। तो mRequest हमेशा सभी टुकड़ों के साथ आखिरी बनाई गई गतिविधि का संदर्भ देता है। इस मामले में findFragmentByTag शून्य नहीं देता है।

  1. उपयोग गतिविधि की दुकान संदर्भ को कमजोर संदर्भ:

    इस समस्या को मेरा सुझाव से बचने के लिए। इस तरह कुछ:
    private WeakReference<RequestCustomerDetails> mRequest;
  2. इस संदर्भ को अद्यतन करने के लिए HeadlessCustomerDetailFetchFragment में कोई विधि बनाएं।
    public void updateResultProcessor(RequestCustomerDetails requestCustomerDetails) { mRequest = new WeakReference(requestCustomerDetails); // Update ui if there is stored result of AsyncTask (see p.4b) }
  3. इस विधि को गतिविधि के ऑनक्रेट() से हर बार कॉल करें।
  4. जब AsyncTask समाप्त होता है:
    ए) यदि mRequest.get()null नहीं है तो यूआई अपडेट करें।
    बी) यदि mRequest.get()null है तो परिणाम को हेडलेस टुकड़े के अंदर स्टोर करें और इसे पी 2 में उपयोग करें।

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

    आशा है कि इससे मदद मिलेगी। मेरी अंग्रेजी के लिए खेद है। अगर कुछ अस्पष्ट है तो मैं समझाने की कोशिश करूंगा।
+0

बाद में इसमें देखेंगे लेकिन यहां बक्षीस है, यह एक सही उत्तर की तरह दिखता है इसलिए धन्यवाद –

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