2012-03-28 15 views
22

एंड्रॉयड प्लेटफॉर्म टुकड़ा के कंटेनर आईडी नहीं बदला जा सकता:IllegalStateException:

private void reattach(int newContainerId, Fragment frag, String tag) { 

     if (frag == null || !frag.isAdded() || (frag.getId() == newContainerId)) { return; } 

     final FragmentManager fm = getFragmentManager(); 
     FragmentTransaction ft = fm.beginTransaction(); 
     ft.remove(frag);  //stacco il frammento dal container A 
     ft.commit(); 
     fm.executePendingTransactions(); 

     ft = fm.beginTransaction(); 
     ft.add(newContainerId, frag, tag); //attacco il frammento sul container D 
     ft.commit(); 
     fm.executePendingTransactions(); 
    } 
: 3.1

मैं एक कंटेनर एक से एक कंटेनर बी यहाँ करने के लिए एक टुकड़ा ले जाने के लिए कोशिश कर रहा हूँ यह पूरा करने के कोड इस प्रकार

जब मैं सिस्टम को चलाने, मैं निम्नलिखित IllegalStateException मिलती है:

03-26 00:13:14.829: E/AndroidRuntime(30090): java.lang.RuntimeException: Unable to start activity ComponentInfo{eu.areamobile.apps.sfa/eu.areamobile.apps.sfa.activity.HomeActivity}: java.lang.IllegalStateException: Can't change container ID of fragment FragmentHomeController{408202a8 id=0x7f050010 HomeController}: was 2131034128 now 2131034132 
03-26 00:13:14.829: E/AndroidRuntime(30090): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1751) 
03-26 00:13:14.829: E/AndroidRuntime(30090): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1767) 
03-26 00:13:14.829: E/AndroidRuntime(30090): at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3117) 
03-26 00:13:14.829: E/AndroidRuntime(30090): at android.app.ActivityThread.access$1600(ActivityThread.java:122) 
03-26 00:13:14.829: E/AndroidRuntime(30090): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1009) 
03-26 00:13:14.829: E/AndroidRuntime(30090): at android.os.Handler.dispatchMessage(Handler.java:99) 
03-26 00:13:14.829: E/AndroidRuntime(30090): at android.os.Looper.loop(Looper.java:132) 
03-26 00:13:14.829: E/AndroidRuntime(30090): at android.app.ActivityThread.main(ActivityThread.java:4028) 
03-26 00:13:14.829: E/AndroidRuntime(30090): at java.lang.reflect.Method.invokeNative(Native Method) 
03-26 00:13:14.829: E/AndroidRuntime(30090): at java.lang.reflect.Method.invoke(Method.java:491) 
03-26 00:13:14.829: E/AndroidRuntime(30090): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:844) 
03-26 00:13:14.829: E/AndroidRuntime(30090): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:602) 
03-26 00:13:14.829: E/AndroidRuntime(30090): at dalvik.system.NativeStart.main(Native Method) 
03-26 00:13:14.829: E/AndroidRuntime(30090): Caused by: java.lang.IllegalStateException: Can't change container ID of fragment FragmentHomeController{408202a8 id=0x7f050010 HomeController}: was 2131034128 now 2131034132 
03-26 00:13:14.829: E/AndroidRuntime(30090): at android.app.BackStackRecord.doAddOp(BackStackRecord.java:338) 
03-26 00:13:14.829: E/AndroidRuntime(30090): at android.app.BackStackRecord.add(BackStackRecord.java:316) 
03-26 00:13:14.829: E/AndroidRuntime(30090): at eu.areamobile.apps.sfa.activity.HomeActivity.reattach(HomeActivity.java:340) 
03-26 00:13:14.829: E/AndroidRuntime(30090): at eu.areamobile.apps.sfa.activity.HomeActivity.customHideShowCreate(HomeActivity.java:253) 
03-26 00:13:14.829: E/AndroidRuntime(30090): at eu.areamobile.apps.sfa.activity.HomeActivity.customHideShowCreate(HomeActivity.java:155) 
03-26 00:13:14.829: E/AndroidRuntime(30090): at eu.areamobile.apps.sfa.activity.HomeActivity.onPostCreate(HomeActivity.java:66) 
03-26 00:13:14.829: E/AndroidRuntime(30090): at android.app.Instrumentation.callActivityOnPostCreate(Instrumentation.java:1111) 
03-26 00:13:14.829: E/AndroidRuntime(30090): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1734) 

एक त्वरित डिबग करने के बाद, मैंने देखा है एंड्रॉयड 3.1 पर FragmentTransaction.remove करने के लिए सेट नहीं है कि 0 टुकड़े टुकड़े के mContainerId हटाया जा रहा है, जबकि आईसीएस पर यह सही ढंग से काम करता है।
कोई सुझाव या कामकाज?

+0

हाय! मेरी भी यही समस्या है। क्या आपने इसे सिस्टम पर पहले से काम करने में कामयाब रहे हैं? – Anton

उत्तर

0

पर Fragment Developer Guide आधार पर यह कहा गया है:

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

तो मुझे लगता है कि अपने frag वस्तु

के लिए कॉल के बाद नष्ट हो जाता है
ft.remove(frag);  //stacco il frammento dal container A 
ft.commit(); 

लेकिन आप कहते हैं कि यह आईसीएस में काम करता है और यह अजीब है। आप replace विधि का प्रयास क्यों नहीं करते हैं और देखें कि क्या होता है?

आशा इस मदद करता है ...

0

कोशिश) की जगह उपयोग करने के लिए (दो बार के लिए प्रतिबद्ध का उपयोग नहीं करते नहीं method..If।

0

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

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

धन्यवाद, डेविड

+0

मैंने यह कोशिश की है - यह काम नहीं करता है। –

18

इस समस्या का समाधान मेरे जबकि इसके राज्य रखने टुकड़ा फिर से बनाने के लिए है:

private Fragment recreateFragment(Fragment f) 
    { 
     try { 
      Fragment.SavedState savedState = mFragmentManager.saveFragmentInstanceState(f); 

      Fragment newInstance = f.getClass().newInstance(); 
      newInstance.setInitialSavedState(savedState); 

      return newInstance; 
     } 
     catch (Exception e) // InstantiationException, IllegalAccessException 
     { 
      throw new RuntimeException("Cannot reinstantiate fragment " + f.getClass().getName(), e); 
     } 
    } 

यह: निम्नलिखित सहायक समारोह के साथ

FragmentTransaction ft = mFragmentManager.beginTransaction(); 
ft.remove(old); 
Fragment newInstance = recreateFragment(old); 
ft.add(R.id.new_container, newInstance); 
ft.commit(); 

मेरे लिए काम करता है, कम से कम नवीनतम समर्थन पुस्तकालय (आर 11) के साथ, हालांकि मैंने अभी तक बहुत परीक्षण नहीं किया है।

अतिरिक्त लागत दो बार टुकड़े को तुरंत चालू करना है।

+0

मुझे तत्काल अपवाद मिल रहा है। इसे कैसे हल करें। –

+0

@ रेथिनवेल पिल्लई विवरण के बिना कहना असंभव है। – sstn

+0

जब डिवाइस रोटेशन हो तो मैं इस कोड को पेस्ट कर सकता हूं? – Tomas

12

समान प्रश्नों से सभी उत्तरों की कोशिश करने के बाद, ऐसा लगता है कि मुझे चाल करने का कोई तरीका मिला है।

सबसे पहले मुद्दा - क्या तुम सच में है प्रतिबद्ध और एक और कंटेनर के लिए टुकड़ा जोड़ने के लिए प्रयास करने से पहले निकालें लेनदेन निष्पादित करने के लिए। इसके लिए धन्यवाद nave's answer

लेकिन यह हर बार काम नहीं करता है। दूसरा मुद्दा एक बैक स्टैक है। यह किसी भी तरह लेनदेन को ब्लॉक करता है।

तो पूरा कोड, कि मेरे लिए काम करता लगता है:

manager.popBackStackImmediate(null, FragmentManager.POP_BACK_STACK_INCLUSIVE); 
manager.beginTransaction().remove(detailFragment).commit(); 
manager.executePendingTransactions(); 
manager.beginTransaction() 
    .replace(R.id.content, masterFragment, masterTag) 
    .add(R.id.detail, detailFragment, activeTag) 
    .commit();    
1

मैं टुकड़ा दूसरी बार के लिए किया था मेरे लिए चाल जोड़ने से पहले एक ऐसी ही समस्या और बुला manager.executePendingTransactions() था। धन्यवाद!

0

क्या खराब प्रोग्रामिंग प्रिंसिपल से अलग कोई वैध कारण है, कि आप एक गतिविधि या दो में किसी भी मौजूदा टुकड़े का संदर्भ रखना चाहते हैं? टुकड़े की स्थिति को बचाने और बस इसे पुनर्निर्माण करने के बजाय?

मैं निर्माण कर रहा है का उपयोग कर टुकड़े:

public static ContactsFragment mContactsFragment; 

    public static ContactsFragment getInstance() { 
    if (mContactsFragment == null) { 
     mContactsFragment = new ContactsFragment(); 
    } 
    return mContactsFragment; 
} 

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

क्यों नहीं होगा आप:

public static ContactsFragment newInstance(Context c) { 
    ContactsFragment mContactsFragment = new ContactsFragment(); 
    mContext = c; 
    return mContactsFragment; 
} 

और बस किसी भी काम आप टुकड़ा पर किया और इसे पुन: जब आप इसे फिर से जरूरत के बाद सहेजें? शायद मैं कल्पना कर सकता हूं कि क्या आप 100+ (समाचार ऐप?) बना रहे थे, तो हो सकता है कि आप उन्हें हर बार बनाना न चाहें, बल्कि उन्हें स्मृति में संग्रहीत करें? किसी को?

0

तो, मुझे एक ही समस्या थी, और समस्या को एक अलग तरीके से हल किया (कम से कम थोड़ा सा)। मेरे ऐप में 4 टुकड़े हैं और जब मेरा डिवाइस लैंडस्केप मोड पर है तो मुझे प्रबंधित करने की आवश्यकता है।व्यंजनों (जो व्यंजनों की एक सूची शामिल) 2 - - सामग्री (की एक सूची 1:

मेरे एप्लिकेशन मैं अपने अनुप्रयोग में 4 टुकड़े है:

मुझे मेरे अनुप्रयोग और समाधान स्पष्ट करता हूं चुनिंदा नुस्खा से सामग्री) 3 - कदम (कदम की सूची) 4 - प्लेयर (एक टुकड़ा है कि) वीडियो खेलने के लिए

पोर्ट्रेट मोड पर मैं कोई समस्या नहीं था कहा जाता है, सब ठीक काम करता है!

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

मुझे यह समस्या है, जब पोर्ट्रेट मोड पर, मेरा टुकड़ा दिखा रहा है, और जब मैं अपने डिवाइस को घुमाता हूं, तो मुझे वही खंड चाहिए जो विस्तार कंटेनर पर जाने के लिए दिखा रहा था। और वह वहीं जहां मेरी सभी समस्याएं शुरू हुईं।

मेरे समाधान

  1. सहेजें पिछले टुकड़ा एक चर में पता चला है;
  2. सहेजे गए इंस्टेंस पर राज्य खंड को सहेजें;
  3. ऑनक्रेट में टुकड़ा पुनर्प्राप्त करें और अंतिम टुकड़ा दिखाया गया है।

तो, अधिक especific होने के लिए मैं मदद करने के लिए https://gist.github.com/jillesRagonha/4c184165b92fdf026ab3cd033b64b1bf

आशा है कि यह सार बनाई गई इस मदद किसी को भी: डी

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