टुकड़े के भीतर टुकड़े


145

मैं सोच रहा था कि क्या यह वास्तव में Android API में एक बग है:

मेरे पास ऐसा सेटअप है:

┌----┬---------┐
|    |         |
|  1 |    2    |
|    |┌-------┐|
|    ||       ||
|    ||   3   ||
└----┴┴-------┴┘
  1. एक मेनू है जो दाहिने फलक में खंड 2 (A खोज स्क्रीन) लोड करता है।
  2. एक खोज स्क्रीन है जिसमें # 3 टुकड़ा है, जो एक परिणाम सूची है।
  3. परिणाम सूची का उपयोग कई स्थानों पर किया जाता है (जिसमें यह अपने आप में एक उच्च स्तरीय टुकड़े के रूप में शामिल है)।

यह कार्यक्षमता एक फोन पर पूरी तरह से अच्छी तरह से काम करती है (जहां 1 और 2 और 3 ActivityFragmentएस हैं)।

हालाँकि, जब मैंने इस कोड का उपयोग किया था:

    FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();       
    Fragment frag = new FragmentNumber2();
    if(toLoad != null) frag.setArguments(toLoad);
    transaction.replace(R.id.rightPane, frag);      
    transaction.commit();

कहाँ R.id.leftPaneऔर R.id.rightPaneकर रहे हैं <fragment>एक क्षैतिज रेखीय लेआउट में रों।

यह मेरी समझ है कि उपरोक्त कोड उस टुकड़े को हटा देता है जो निवासी है और फिर इसे एक नए टुकड़े के साथ बदल देता है। शानदार ... जाहिर है कि ऐसा नहीं होता है क्योंकि जब यह कोड दूसरी बार चलता है तो आपको निम्न अपवाद मिलते हैं:

07-27 15:22:55.940: ERROR/AndroidRuntime(8105): Caused by: java.lang.IllegalArgumentException: Binary XML file line #57: Duplicate id 0x7f080024, tag null, or parent id 0x0 with another fragment for FragmentNumber3

यह इसलिए होता है क्योंकि FragmentNumber3 के लिए कंटेनर को डुप्लिकेट किया गया है और इसमें अब एक विशिष्ट आईडी नहीं है। आरंभिक फ्रैगमेंट को नष्ट नहीं किया गया है (?) इससे पहले कि नया जोड़ा जाए (मेरे दिमाग में) इसका मतलब यह नहीं है प्रतिस्थापित गया है )।

क्या कोई मुझे बता सकता है कि क्या यह संभव है ( यह उत्तर बताता है कि यह नहीं है) या यह एक बग है?



6
@ यह एक प्राचीन प्रश्न है, डुप्लिकेट के रूप में चिह्नित करने के लिए थोड़ा व्यर्थ है।
pietv8x

जवाबों:


203

नेस्टेड टुकड़े वर्तमान में समर्थित नहीं हैं। एक और टुकड़े के UI के भीतर एक टुकड़ा डालने की कोशिश करने से अपरिभाषित और संभावित रूप से टूटे हुए व्यवहार का परिणाम होगा।

अद्यतन : नेस्टेड टुकड़े Android 4.2 (और एंड्रॉइड सपोर्ट लाइब्रेरी रिव 11) के रूप में समर्थित हैं : http://developer.android.com/about/versions/android-4.2.html#NestedFragments

नोट ( इस डॉक्स के अनुसार ): " नोट: जब आप उस लेआउट को शामिल करते हैं तो आप किसी टुकड़े को लेआउट में नहीं बढ़ा सकते हैं <fragment>। नेस्टेड फ्रेगमेंट केवल तब ही समर्थित होते हैं जब किसी टुकड़े को गतिशील रूप से जोड़ा जाता है। "


14
समर्थित नहीं है क्योंकि यह प्रारंभिक कार्यान्वयन के लिए एक डिज़ाइन लक्ष्य नहीं था। मैंने फीचर के लिए बहुत सारे अनुरोध सुने हैं, इसलिए यह संभवत: किसी बिंदु पर किया जाएगा, लेकिन हमेशा की तरह बहुत सारी अन्य चीजें प्राथमिकता में हैं।
हैकबॉड

4
मैंने इसे FragmentActivity, FragmentManager और FragmentTransaction का विस्तार करके प्रबंधित किया। मूल आधार का विस्तार है मेरी गतिविधियों में FindFragmentActivity, वही एपीआई प्रदान करना ताकि कोई अन्य कोड परिवर्तन न हो। जब मैं getFragmentManager को कॉल करता हूं, तो मुझे एक उदाहरण मिलता है कि FindFragmentManager, और जब मैं startTransaction कहता हूं, तो मुझे एक DeferredTransaction मिलता है। यह लेनदेन पीओजेओ को तथाकथित विधि और तर्कों के साथ संग्रहीत करता है। जब प्रतिबद्ध कॉल होता है, तो हम पहले किसी लंबित DeferredTransactions की तलाश करते हैं। एक बार सभी लेनदेन किए जाने के बाद, हम एक वास्तविक लेन-देन शुरू करते हैं और सभी संग्रहीत तरीकों को आर्ग के साथ चलाते हैं।
डस्किनर

11
वह बिंदु अब है। नेस्टेड Fragments अब Android API, yay का हिस्सा हैं! डेवलपर .android.com/about/versions/…
एलेक्स लॉकवुड

9
वाह, क्या बुरा सपना: यदि आप एक टुकड़े पर <टुकड़ा> का उपयोग करते हैं, और यह टुकड़ा बच्चे के टुकड़े का उपयोग करने के लिए होता है, तो यह एक स्पष्ट त्रुटि के साथ विफल नहीं होता है ("टुकड़े टुकड़े करने के लिए बच्चे के टुकड़े जोड़ नहीं सकते") - यह "टुकड़े टुकड़े नहीं किया था" जैसे अपवादों के साथ रहस्यमय तरीके से विफल रहता है। डिबगिंग के कई घंटे चलते हैं ...
ग्लेन मेनार्ड

6
@ MartínMarconcini यकीन है, लेकिन यह एपीआई द्वारा प्रदान की गई कार्यक्षमता के आधार पर बिल्कुल स्पष्ट नहीं है। यदि किसी चीज़ की अनुमति नहीं है तो उसे स्पष्ट रूप से प्रलेखित किया जाना चाहिए , न कि डेवलपर को उनके बालों को बाहर खींचने के लिए छोड़ दिया जाए क्योंकि कुछ उस तरीके से काम नहीं कर रहा है जिस तरह से आप उम्मीद करेंगे।
dcow

98

नेस्टेड टुकड़े Android 4.2 और बाद में समर्थित हैं

एंड्रॉइड सपोर्ट लाइब्रेरी अब नेस्टेड टुकड़ों का भी समर्थन करती है , इसलिए आप एंड्रॉइड 1.6 और उच्चतर पर नेस्टेड टुकड़ा डिजाइनों को लागू कर सकते हैं।

एक टुकड़ा घोंसला करने के लिए, बस उस टुकड़े पर getChildFragmentManager () कॉल करें जिसमें आप एक टुकड़ा जोड़ना चाहते हैं। यह एक FragmentManager देता है जिसे आप उपयोग कर सकते हैं जैसे आप सामान्य रूप से शीर्ष-स्तरीय गतिविधि से टुकड़ा लेनदेन बनाने के लिए करते हैं। उदाहरण के लिए, यहां कुछ कोड है जो एक मौजूदा फ्रैगमेंट वर्ग के भीतर से एक खंड जोड़ता है:

Fragment videoFragment = new VideoPlayerFragment();
FragmentTransaction transaction = getChildFragmentManager().beginTransaction();
transaction.add(R.id.video_fragment, videoFragment).commit();

नेस्टेड टुकड़ों के बारे में अधिक विचार प्राप्त करने के लिए, कृपया इन ट्यूटोरियल
भाग 1
भाग 2
भाग 3 के माध्यम से जाएँ

और यहाँ एक SO पोस्ट है जो नेस्टेड टुकड़ों के लिए सर्वोत्तम प्रथाओं के बारे में चर्चा करता है ।


Nestedfragment का मुख्य नुकसान यह है कि हम चाइल्डफ्रैगमेंट से optionmenu को कॉल नहीं कर सकते हैं :( अगर हम ABS का उपयोग कर रहे हैं!
LOG_TAG

क्या आप कृपया मेरे मुद्दे को देख सकते हैं ?? इसके बहुत समान .. stackoverflow.com/questions/32240138/… । मेरे लिए चाइल्ड फ्रैमेनेट कोड से फुलाया नहीं जा रहा है
निक्स

33

.. आप माता-पिता के टुकड़े की destroyviewविधि में अपने घोंसले के टुकड़े को साफ कर सकते हैं :

@Override
    public void onDestroyView() {

      try{
        FragmentTransaction transaction = getSupportFragmentManager()
                .beginTransaction();

        transaction.remove(nestedFragment);

        transaction.commit();
      }catch(Exception e){
      }

        super.onDestroyView();
    }

4
यदि आप SetAlwaysFinish ( bricolsoftconsulting.com/2011/12/23/… ) के साथ कुछ जीवनचक्र परीक्षण करते हैं , तो आप देखेंगे कि यह कोड त्रुटि का कारण बनता है जब कोई अन्य गतिविधि हमेशा समाप्त होने के साथ शीर्ष पर जाती है (IllegalateateException: इस क्रिया को निष्पादित नहीं कर सकता onSaveInstanceState के बाद)। कोशिश / पकड़ में ऊपर कोड लपेटना सबसे सुंदर समाधान नहीं है, लेकिन यह सब कुछ काम करने लगता है।
थियो

यह लगभग काम कर गया। बाद में मुझे UI आकर्षित करने पर एक Stackoverflow मिला। निश्चित रूप से नेस्टेड टुकड़ों से बचें ...
neteinstein

14

मेरे पास एक ऐसा एप्लिकेशन है जिसे मैं विकसित कर रहा हूं जो कि खंडों में लॉन्च होने वाले एक्शन बार में टैब्स के समान है, इनमें से कुछ फ्रैगमेंट में कई एम्बेडेड फ्रैगमेंट हैं।

जब मैंने एप्लिकेशन को चलाने का प्रयास किया तो मुझे वही त्रुटि मिल रही थी। ऐसा लगता है कि यदि आप एक टैब अचयनित होने के बाद xml लेआउट के भीतर फ्रेग्मेंट्स को तुरंत हटा देते हैं और फिर से हटा दिया जाता है तो मुझे इनफ्लोटर त्रुटि मिलेगी।

मैंने इसे xml में सभी टुकड़ों को Linearlayouts के साथ हल किया और फिर एक टुकड़े प्रबंधक का उपयोग करके टुकड़े को सब कुछ तुरंत करने के लिए एक परीक्षण स्तर पर कम से कम सही ढंग से काम करने के लिए लगता है।

मुझे आशा है कि यह आपकी मदद करेगा।


क्या कोई इस दृष्टिकोण की प्रभावशीलता पर टिप्पणी कर सकता है? मुझे लगता है कि यह केवल एक स्तर तक फ्रैगमेंट का उपयोग करने में सक्षम होने के लिए दुर्भाग्यपूर्ण है - हो सकता है कि तब भी उनका उपयोग न करें। उन्हें प्लेसहोल्डर व्यूग्रुप्स पर प्रोग्रामेटिक रूप से जोड़ना बिना कैविट के काम करेगा?
राफेल नोब्रे

अभी भी मेरे लिए काम कर रहा है, मैं उन्हें देखने के लिए और साथ ही साथ कोई समस्या नहीं है। एक चेतावनी मैं केवल आइसक्रीम सैंडविच के अनुकूलता के साथ नहीं छत्ते पर यह कर रहा हूं।
दैनिक

4

मैंने एक ही समस्या का सामना किया है, इसके साथ कुछ दिन संघर्ष किया है और यह कहना चाहिए कि मैंने इसे दूर करने के लिए सबसे आसान तरीका यह पाया है कि टैब का चयन / अचयनित होने पर खंड ()ide) (/ fragment.show () का उपयोग करें। ()।

public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction ft)
{
    if (mFragment != null)
        ft.hide(mFragment);
}

जब स्क्रीन रोटेशन होता है तो सभी माता-पिता और बच्चे के टुकड़े सही ढंग से नष्ट हो जाते हैं।

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

समस्या यह है कि मुझे पता नहीं है कि जब वे दिखाई नहीं देते हैं तो टुकड़ों को अलग नहीं करना सही है या नहीं। मुझे लगता है कि TabListener का आधिकारिक उदाहरण मन में एक विचार के साथ बनाया गया है कि टुकड़े पुन: प्रयोज्य हैं और आपको उनके साथ स्मृति को प्रदूषित नहीं करना चाहिए, हालांकि, मुझे लगता है कि यदि आपके पास बस कुछ टैब हैं और आप जानते हैं कि उपयोगकर्ता इसे बीच-बीच में स्विच करते रहेंगे। उन्हें वर्तमान गतिविधि से जोड़े रखने के लिए उपयुक्त होगा।

मैं अधिक अनुभवी डेवलपर्स से टिप्पणियां सुनना चाहूंगा।


0

यदि आप पाते हैं कि आपका नेस्टेड टुकड़ा हटाया नहीं जा रहा है या डुप्लिकेट नहीं किया जा रहा है (जैसे, एक्टिविटी रिस्टार्ट, स्क्रीन रोटेट पर) बदलने की कोशिश करें:

transaction.add(R.id.placeholder, newFragment);

सेवा

transaction.replace(R.id.placeholder, newFragment);

यदि ऊपर मदद नहीं करता है, तो कोशिश करें:

Fragment f = getChildFragmentManager().findFragmentById(R.id.placeholder);

FragmentTransaction transaction = getChildFragmentManager().beginTransaction();

if (f == null) {
    Log.d(TAG, "onCreateView: fragment doesn't exist");
    newFragment= new MyFragmentType();
    transaction.add(R.id.placeholder, newFragment);
} else {
    Log.d(TAG, "onCreateView: fragment already exists");
    transaction.replace(R.id.placeholder, f);
}
transaction.commit();

यहां सीखा है

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.