क्या यह एक गहरी नेस्टेड स्टैक छोड़ने पर फ्रैगमेंट बैक स्टैक को साफ करने का सही तरीका है?


130

मैं टुकड़ों को लागू करने के लिए एंड्रॉइड कम्पेटिबिलिटी लाइब्रेरी का उपयोग कर रहा हूं और लेआउट के नमूने को बढ़ा दिया है ताकि एक टुकड़े में एक बटन हो जो एक और टुकड़े से निकलता है।

बाईं ओर चयन फलक में मेरे पास 5 चुनिंदा आइटम हैं - A B C D E

प्रत्येक FragmentTransaction:replaceविवरण में एक टुकड़ा (के माध्यम से ) फलक लोड करता है -a b c d e

अब मैंने eएक बटन रखने के लिए टुकड़े को बढ़ाया है जो e1विवरण फलक में एक और टुकड़ा भी लोड करता है । मैंने इसे इस eप्रकार किया है:

FragmentTransaction ft = getActivity().getSupportFragmentManager().beginTransaction();
ft.replace(R.id.details_frag, newFrag);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
ft.addToBackStack(null);
ft.commit();

अगर मैं निम्नलिखित चयन करूं:

E - e - e1 - D - E

फिर टुकड़ा eविवरण फलक में है। यह ठीक है और मैं जो चाहता हूं। हालांकि, अगर मैं backइस बिंदु पर बटन दबाता हूं तो यह कुछ नहीं करता है। मुझे इसे दो बार क्लिक करना होगा क्योंकि e1स्टैक पर अभी भी है। इसके अलावा आसपास क्लिक करने के बाद मुझे onCreateView में एक शून्य सूचक अपवाद मिला:

इस समस्या को 'हल' करने के लिए जब भी मुझे चुना गया है, तो मैंने उसे जोड़ा A B C D E:

FragmentManager fm = getActivity().getSupportFragmentManager();
for(int i = 0; i < fm.getBackStackEntryCount(); ++i) {
    fm.popBackStack();
}

बस सोच रहा था कि क्या यह सही समाधान है या क्या मुझे कुछ अलग करना चाहिए?

जवाबों:


252

वैसे इसके बारे में जाने के लिए कुछ तरीके हैं जो इच्छित व्यवहार के आधार पर हैं, लेकिन इस लिंक से आपको सभी बेहतरीन समाधान मिल सकते हैं और आश्चर्यजनक रूप से यह डायने हैकॉर्न से नहीं है

http://groups.google.com/group/android-developers/browse_thread/thread/d2a5c203dad6ec42

अनिवार्य रूप से आपके पास निम्नलिखित विकल्प हैं

  • अपने प्रारंभिक बैक स्टैक स्थिति के लिए एक नाम का उपयोग करें और उपयोग करें FragmentManager.popBackStack(String name, FragmentManager.POP_BACK_STACK_INCLUSIVE)
  • बैक स्टैक पर पहली प्रविष्टि की आईडी प्राप्त करने के लिए FragmentManager.getBackStackEntryCount()/ getBackStackEntryAt().getId()का उपयोग करें , और FragmentManager.popBackStack(int id, FragmentManager.POP_BACK_STACK_INCLUSIVE)
  • FragmentManager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE) पूरे बैक स्टैक को पॉप करने के लिए माना जाता है ... मुझे लगता है कि इसके लिए प्रलेखन सिर्फ गलत है। (वास्तव में मुझे लगता है कि यह उस मामले को कवर नहीं करता है जहाँ आप पास हैं POP_BACK_STACK_INCLUSIVE),

इसका क्या मतलब है? FragmentManager.getBackStackEntryCount () / getBackStackEntryt ()। GetId ()
dannyroa

4
दूसरा मेरे लिए काम किया। पूरे स्टैक को साफ़ करने के लिए इसका क्या अर्थ है: getSupportFragmentManager ()। popBackStack (getSupportFragmentManager ()। GetBackStackEntryAt (0) .getId) (, FragmentManager.POP_BACK_STACK_INCLUSIVE)।
निकोल

@JorgeGarcia पॉपबैकस्ट के बाद यह संभव है कि हम अपने खंड को पुराने के बिना फिर से शुरू करें।
डुग्गु

कृपया ध्यान दें कि popBackStackImmediate () संस्करण भी है क्योंकि popBackStack () async है, जिसका अर्थ है कि जिस विधि को आप कॉल करते हैं, ठीक उसी समय क्लियरिंग नहीं होती है।
Genc

6
दावा है कि समूह को स्पैम के रूप में प्रतिबंधित किया गया है और मैं लिंक का उपयोग नहीं कर सकता :( क्या किसी के पास कहीं और संसाधन है?
EpicPandaForce

61

अन्य साफ समाधान अगर आप सभी स्टैक प्रविष्टियों को पॉप नहीं करना चाहते हैं ...

getSupportFragmentManager().popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
getSupportFragmentManager().beginTransaction().replace(R.id.home_activity_container, fragmentInstance).addToBackStack(null).commit();

यह पहले स्टैक को साफ करेगा और फिर एक नया टुकड़ा लोड करेगा, इसलिए किसी भी बिंदु पर आपको स्टैक में केवल एक ही टुकड़ा होगा


1
: यह बहुत खराब है getSupportFragmentManager().popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);() से पहले एक की जगह क्योंकि टुकड़ा बुला लोड कर रहे हैं onCreateView(), onActivityCreated()आदि पुनर्स्थापित कर रहा है और Destroing एक टुकड़ा तुरन्त बुरा है। Fragment उदाहरण के लिए एक रिसीवर को पंजीकृत कर सकता है। इससे प्रदर्शन प्रभावित होता है।
VasileM

@VasileM, क्या आप विवरण में वर्णन कर सकते हैं? किन मामलों में यह बुरा है? क्या यह अतुलनीय व्यवहार के कारण है FragmentTransaction? क्या गलत विखंडन स्टैक का केवल बुरा प्रदर्शन है?
कूलमाइंड

27

जोआचिम उत्तर के लिए धन्यवाद , मैं अंत में सभी स्टैक प्रविष्टि को खाली करने के लिए कोड का उपयोग करता हूं।

// In your FragmentActivity use getSupprotFragmentManager() to get the FragmentManager.

// Clear all back stack.
int backStackCount = getSupportFragmentManager().getBackStackEntryCount();
for (int i = 0; i < backStackCount; i++) {

    // Get the back stack fragment id.
    int backStackId = getSupportFragmentManager().getBackStackEntryAt(i).getId();

    getSupportFragmentManager().popBackStack(backStackId, 
        FragmentManager.POP_BACK_STACK_INCLUSIVE);

} /* end of for */

18
यहाँ एक लूप का उपयोग क्यों करें? मेरे लिए FragmentManager.popBackStack (null, FragmentManager.POP_BACK_STACK_INCLUSIVE) ने सभी बैक स्टैक एंट्री को मंजूरी दे दी ...
Marek

3
@ मर्क, क्योंकि कभी-कभी सभी टुकड़ों को नहीं हटाया जाना चाहिए, इसके लिए एक लूप उपयुक्त है।
18

1
@CoolMind, कि अभी भी मेरे लिए कोई मतलब नहीं है। popBackStack(backStackId, INCLUSIVE)सभी खंडों (राज्यों) को बैकस्टैकआईड पर पॉप करेगा, इसलिए एक बार जब आप सबसे कम पॉप करते हैं, तो आप iसभी उच्चतर लोगों को एक ही समय में पॉपप हो जाना चाहिए। तो एक लूप की बात क्या है?
15

@ लर्ष, आप सही कह रहे हैं। Stackoverflow.com/a/59158254/2914140 देखें । आवश्यक टैग के लिए अन्य टुकड़ों को पॉप करने के लिए, हमें सबसे पहले addToBackStack ( टैग ) के साथ टुकड़ा जोड़ना चाहिए ।
कूलमाइंड

7

मैंने बैकस्टैक की सफाई के लिए बहुत शोध किया है, और अंत में ट्रांजेक्शन बैकस्टैक और इसके प्रबंधन को देखें । यहाँ समाधान है कि मेरे लिए सबसे अच्छा काम किया है।

 // CLEAR BACK STACK.
    private void clearBackStack() {
        final FragmentManager fragmentManager = getSupportFragmentManager();
        while (fragmentManager.getBackStackEntryCount() != 0) {
            fragmentManager.popBackStackImmediate();
        }
    }

उपरोक्त विधि बैकस्टैक में सभी लेनदेन पर लूप करती है और उन्हें एक बार में तुरंत हटा देती है।

नोट: उपरोक्त कोड कुछ समय के लिए काम नहीं करता है और मुझे इस कोड के कारण ANR का सामना करना पड़ता है , इसलिए कृपया यह प्रयास न करें।

नीचे दी गई विधि अद्यतन बैकस्टैक से उस "नाम" के सभी फ़्रीलेशन को हटा दें।

FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.popBackStack("name",FragmentManager.POP_BACK_STACK_INCLUSIVE);
  • नाम यदि गैर-अशक्त है, तो यह पिछली पीठ की स्थिति का नाम है; अगर पाया जाता है, तो उस राज्य के सभी राज्य पॉप-अप हो जाएंगे।
  • POP_BACK_STACK_INCLUSIVE ध्वज का उपयोग यह नियंत्रित करने के लिए किया जा सकता है कि नामांकित राज्य स्वयं पॉप है। यदि अशक्त, केवल शीर्ष स्थिति पॉप है।

मैं नहीं देखता कि आप उन्हें एक बार में क्यों हटाएंगे। क्या कोई कारण है कि आपने अन्य समाधानों के बजाय इस समाधान के लिए चुना? क्या एक बार में सभी के बजाय एक बार उन्हें हटाने का कारण है?
miva2

एक बार में बैकस्टैक निकालने की कोई विधि नहीं है। डेवलपर
लोकेश

3

मैं एक समान कोड का उपयोग कर रहा हूं जो कि लूप का उपयोग करते हैं, लेकिन मैं प्रत्येक लूप में प्रवेश गणना कहता हूं ... इसलिए मुझे लगता है कि यह कुछ धीमा है

FragmentManager manager = getFragmentManager();
while (manager.getBackStackEntryCount() > 0){
        manager.popBackStackImmediate();
    }

0

के रूप में लिखा था कि कैसे बैकस्टैक से पॉप टुकड़ा और में LarsH यहाँ, हम specifical टैग करने के लिए शीर्ष नीचे (से कई टुकड़े पॉप कर सकते हैं एक साथ टैग टुकड़ा के साथ ) इस पद्धति का उपयोग:

fragmentManager?.popBackStack ("frag", FragmentManager.POP_BACK_STACK_INCLUSIVE);

अपने टुकड़े के टैग के साथ "सुगंधित" को स्थान दें। याद रखें कि पहले हमें टुकड़े को बैकस्टैक से जोड़ना चाहिए:

fragmentTransaction.addToBackStack("frag")

यदि हम टुकड़ों को जोड़ते हैं addToBackStack(null), तो हम उस तरह से टुकड़ों को पॉप नहीं करेंगे।


-4
    // pop back stack all the way
    final FragmentManager fm = getSherlockActivity().getSupportFragmentManager();
    int entryCount = fm.getBackStackEntryCount(); 
    while (entryCount-- > 0) {
        fm.popBackStack();
    }
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.