IllegalStateException: टैबहॉस्ट टुकड़े में पहले से ही जोड़ा गया टुकड़ा


81
FATAL EXCEPTION: main
Process: com.example.loan, PID: 24169
java.lang.IllegalStateException: Fragment already added: FormFragment{428f10c8 #1 id=0x7f050055 form}
    at android.support.v4.app.FragmentManagerImpl.addFragment(FragmentManager.java:1192)
    at android.support.v4.app.BackStackRecord.popFromBackStack(BackStackRecord.java:722)
    at android.support.v4.app.FragmentManagerImpl.popBackStackState(FragmentManager.java:1533)
    at android.support.v4.app.FragmentManagerImpl$2.run(FragmentManager.java:489)
    at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1484)
    at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:450)
    at android.os.Handler.handleCallback(Handler.java:733)
    at android.os.Handler.dispatchMessage(Handler.java:95)
    at android.os.Looper.loop(Looper.java:136)
    at android.app.ActivityThread.main(ActivityThread.java:5068)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:515)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:792)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:608)
    at dalvik.system.NativeStart.main(Native Method)

तो, मेरे पास एक एंड्रॉइड ऐप है जो टैबहॉस्ट के साथ बनाता है। कुल तीन टैब हैं, टैब 2 में, टैब 2 में टुकड़ा लेनदेन करने के लिए एक बटन है (जो टुकड़ा गतिविधि में फ़ंक्शन को बुला रहा है)

FragmentTransaction t = getSupportFragmentManager().beginTransaction();
        t.replace(R.id.realtabcontent, mFrag);
        t.addToBackStack(null);
        t.commit();

अगर मैं इस तरह से चलाऊ तो ​​अपवाद है:

  1. टैब 2 के अंदर, मैं टुकड़े को बदलने के लिए बटन दबाता हूं
  2. अन्य टैब पर जाएं (उदाहरण के लिए टैब 1 या टैब 3)
  3. बैक बटन दबाएं
  4. अपवाद फेंको

उसे कैसे ठीक करें? मदद के लिए धन्यवाद



इसका मतलब है कि बैकस्पेस एक नया टुकड़ा जोड़ रहा है, बैकस्ट में तर्क क्या है? बहुत बहुत धन्यवाद
user782104

क्या mFrag को tab2 के अलावा कुछ अन्य टैब में भी जोड़ा जाता है?
अखिल

जवाबों:


152

ऐसा तब होता है जब हम खारिज करने से पहले दो बार एक ही खंड या डायलॉगफ्रेगमेंट जोड़ने का प्रयास करते हैं,

बस कॉल करना

if(mFragment.isAdded())
{
     return; //or return false/true, based on where you are calling from
}

ऐसा कहने के बाद, मुझे पुराने टुकड़े को हटाने और फिर से उसी टुकड़े को जोड़ने का कोई कारण दिखाई नहीं देता है क्योंकि हम UI / डेटा को केवल टुकड़े के अंदर विधि में पास करके अद्यतन कर सकते हैं


5
यह स्वीकृत उत्तर होना चाहिए। स्वीकृत उत्तर का कोई मतलब नहीं है। सबसे पहले, कोई भी उपेक्षा नहीं होनी चाहिए isAdded()। दूसरा, टिप्पणियों में, यह सुझाव दिया गया है कि यह कोड अंदर जाता है onCreate(), जो कि निरर्थक भी है। कोड की यह पंक्ति सीधे लाइन जहां टुकड़ा जोड़ दिया जाता है (या बदल), में नहीं से पहले रखा जाना चाहिए onCreate()या onCreateView()। उन विधियों में से किसी एक में उस कोड को निष्पादित करने में बहुत देर हो चुकी है।
AndroidDev

3
if(fragment.isAdded()) fragmentTransaction.show(fragment);
कॉन्सटेंटिन कोनपोको

टुकड़ों को छिपाने के लिए भी जाँच की जानी चाहिए।
महदी मुकादसी

मुझे इसी तरह के टुकड़े जोड़ने की जरूरत है और टुकड़े में केवल विशेषताएँ अलग हैं। लेकिन डुप्लिकेट त्रुटि तब भी होती है।
एल्स्टन

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

12

यदि यह अभी भी जोड़ा गया है तो पुराने टुकड़े को हटा दें और फिर नया टुकड़ा जोड़ें:

FragmentManager fm = getSupportFragmentManager();
Fragment oldFragment = fm.findFragmentByTag("fragment_tag");
if (oldFragment != null) {
    fm.beginTransaction().remove(oldFragment).commit();
}
MyFragment newFragment = new MyFragment();
fm.beginTransaction().add(newFragment , "fragment_tag");

क्या हमें पहले से प्रदर्शित टुकड़े में कोई बदलाव करने के लिए तर्क नहीं भेजने चाहिए? इसे हटाने और फिर से जोड़ने के बजाय
उज्जू

खंड प्रबंधक में अंश जोड़ने के बाद आप तर्क निर्धारित नहीं कर सकते। डॉक्स से: "इस पद्धति को नहीं कहा जा सकता है यदि टुकड़ा को एक फ्रैगमेंट मैनजर में जोड़ा जाता है और यदि स्टेस्टसेव्ड () सही है।" यूआई को अपडेट करना चाहते हैं तो आपको सीधे अपने टुकड़े के तरीकों को कॉल करना होगा।
वोवहॉस्ट

हां, मेरा मतलब है कि सेटिंग के माध्यम से setArguments, अद्यतन करने के लिए तर्क को भेजने के लिए जिक्र किया गया था, इसलिए एक ही टुकड़े को हटाने और जोड़ने का कोई अधिकार नहीं है?
उज्जु

निर्भर करता है। यदि आपको बहुत सी चीजों को फिर से कॉन्फ़िगर करने की आवश्यकता है तो टुकड़े को केवल एक नए के साथ बदलना आसान हो सकता है। यह सब आपकी जरूरतों पर निर्भर करता है।
वोवहॉस्ट

1
मैं त्रुटि प्राप्त करना जारी रखता हूं, यदि एक लेनदेन का उपयोग करें। संभवतः यह खंड प्रबंधक के साथ काम के अतुल्यकालिक व्यवहार के कारण है।
कूलमाइंड

8

आपको बस नीचे उल्लिखित अपनी स्थिति में एक स्थिति की जाँच करनी है:

if(!isAdded())
{
    return;
}

isAdded = यदि यह टुकड़ा वर्तमान में अपनी गतिविधि में जोड़ा जाता है तो सही लौटें। आधिकारिक दस्तावेज से लिया गया। यह उस टुकड़े को नहीं जोड़ेगा यदि यह पहले से ही जोड़ा गया है

एक संदर्भ के लिए नीचे दिए गए लिंक की जाँच करें:
http://developer.android.com/reference/android/app/Fragment.html#isded ()


आपकी मदद के लिए धन्यवाद, क्या आपका मतलब है कि मैं (isAdded ()) oncreateview के अंदर रखता हूं?
user782104

हां, आपको बस उस कोड को रखना होगा जिसका मैंने ऊपर मेरे उत्तर में उल्लेख किया है ... इसका मतलब है कि आपका टुकड़ा पहले से ही स्टैक में जोड़ा गया है। तो, इसे फिर से जोड़ने की आवश्यकता नहीं है और यह बस वापस आ जाता है।
दीप मेहता

6
इसका कोई मतलब नहीं है, आप onCreateView में वापसी नहीं कर सकते, क्या आपका मतलब onCreate था? मैं वहाँ में यह कोशिश की और यह मेरे मुद्दे पर मदद नहीं की
Fonix

5
क्या इसे जोड़ा जाता है onCreate?
स्टुइरलिंग

5
नकार क्यों हस्ताक्षर? क्या टुकड़ा जोड़ा नहीं जाना चाहिए अगर! (एडेड)?
एलन सिल्जाक

7

कभी-कभी यह संबंधित लेआउट से उचित आईडी नहीं ढूंढने के लिए होता है। मैंने इस समस्या का सामना किया। फिर कई घंटों के बाद मैंने पाया कि मैंने गलत recyclerview id सेट की है। मैं इसे बदल देता हूं, और मेरे लिए ठीक काम करता है।

तो, अपने खंड लेआउट को दोहराएं।


2
धन्यवाद, यह मेरे लिए समान था। अपवाद संदेश अधिक भ्रामक नहीं हो सकता है।
23

मूल कारण की जांच के लिए एक महीने से अधिक समय के बाद, यही कारण था। बहुत बहुत धन्यवाद
ओमिद हेशमतीनिया

7

खंडित लेनदेन शुरू करने से पहले आपको बस एक शर्त की जांच करनी होगी

 if (!fragmentOne.isAdded()){
            transaction = manager.beginTransaction();
            transaction.add(R.id.group,fragmentOne,"Fragment_One");
            transaction.commit();
 }

यह मेरे लिए पूरी तरह से काम कर रहा है ...


1

मुझे यह त्रुटि तब होती है जब अपने शरीर XML को फ्रेमलेयआउट के अंदर एक व्यूग्रुप के अंदर लपेटकर नहीं।

त्रुटि:

<FrameLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".screens.home.HomeEpoxyFragment">

    <androidx.swiperefreshlayout.widget.SwipeRefreshLayout
        android:id="@+id/swipe_refresh_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/rv"
            android:overScrollMode="never"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

    </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>

</FrameLayout>

हल किया:

<FrameLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".screens.home.HomeEpoxyFragment">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <androidx.swiperefreshlayout.widget.SwipeRefreshLayout
            android:id="@+id/swipe_refresh_layout"
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <androidx.recyclerview.widget.RecyclerView
                android:id="@+id/rv"
                android:overScrollMode="never"
                android:layout_width="match_parent"
                android:layout_height="match_parent" />

        </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
    </androidx.constraintlayout.widget.ConstraintLayout>

</FrameLayout>

आशा है कि यह किसी की मदद कर सकता है।


0

मेरे लिए यह काम करता है:

Fragment oldFragment = manager.findFragmentByTag(READER_VIEW_POPUP);
if (oldFragment != null) {
    manager.beginTransaction().remove(oldFragment).commit();
}

FragmentTransaction ft = manager.beginTransaction();
ft.add(this, tag);
ft.commit();

0

यह तब भी हो सकता है यदि आप FragmentStatePagerAdapterअपने द्वारा ViewPagerपहले से मौजूद एक वस्तु बनाते हैं:

override fun getItem(position: Int): Fragment {
    return tabs[0] // Right variant: tabs[position]
}

( private val tabs: List<Fragment>टैब में अंशों की एक सूची है)।


आपने इसे कैसे हल किया? यह मेरे उपयोग के मामले के समान है
मिच

@ मिच, मैंने return tabs[position]दूसरी पंक्ति में लिखा है।
CoolMind

मैं भी उसी अवधारणा का उपयोग कर रहा हूं, return tabs[position]लेकिन यह अभी भी एक त्रुटि फेंकता है
मिच

@ मिच, माफ करना, मैं एक कोड के बिना नहीं जानता। सामान्य स्थिति के लिए वर्तमान में मैं stackoverflow.com/a/57161814/2914140 का उपयोग करता हूँ । क्या आपको लगता FragmentStatePagerAdapterहै कि इसमें त्रुटि है getItem?
कूलमाइंड

यह त्रुटि का स्रोत होने की संभावना है क्योंकि यह उस स्थान का है जहां उदाहरण (s) के टुकड़े को दर्शाया गया है ViewPager प्राप्त किए गए हैं
मिच

0

मेरे आश्चर्य के लिए, मैंने दो बार टुकड़ा लेनदेन को कॉल करके बेवकूफ गलती की:

if (!FirebaseManager.isClientA && !FirebaseManager.isClientB) {
      fragment = new FragmentA();
      getFragmentManager().beginTransaction().add(R.id.fragment_frame, fragment, null).addToBackStack("").commit();
} else if (FirebaseManager.isClientB) {
      fragment = new FragmentB();
} else {
      fragment = new FragmentC();
}
getFragmentManager().beginTransaction().add(R.id.fragment_frame, fragment, null).addToBackStack("").commit();

सुनिश्चित करें कि आप एक ही गलती नहीं करते हैं।


0

नीचे के रूप में खुशबू जोड़ें

FragmentTransaction t = getSupportFragmentManager().beginTransaction();
    t.replace(R.id.realtabcontent, mFrag);
    t.addToBackStack(null);
    t.commitNowAllowingStateLoss();

पुराने और नए टुकड़ों के साथ क्या होगा? क्या यह पुराने को नए के साथ बदल देगा?
कूलमाइंड

नहीं, यह प्रतिस्थापित नहीं करेगा यह पिछले टुकड़े को वापस ढेर में जोड़ देगा।
एम। नोमान

मुझे आश्चर्य है, क्या यह संभव है? कल मैंने इसी तरह के कोड की कोशिश की और एक त्रुटि मिली, देखें stackoverflow.com/questions/38566628/… , क्योंकि addToBackStackइसके साथ अनुमति नहीं है commitNow
CoolMind

उस लिंक में, वह मैन्युअल रूप से बैक स्टैक को अक्षम कर रहा है। AddToBackStack के साथ यह खंड के पीछे ढेर को प्रबंधित करने में सक्षम होगा
M.Noman


0

मुझे यह त्रुटि तब मिली जब गलत तरीके से Fragment के अंदर मेरे ViewModel का उपयोग किया गया:

//This is wrong!
MyViewModel viewModel = new MyViewModel(getActivity().getApplication());

सही तरीका:

viewModel = new ViewModelProvider(this, ViewModelProvider.AndroidViewModelFactory.getInstance(getActivity().getApplication())).get(MyViewModel.class);

0

यहाँ संवाद समाधान के लिए मेरा समाधान (आप इस अवधारणा का उपयोग टुकड़े वर्ग के लिए भी कर सकते हैं)

मैंने कई बार और जल्दी से टैप बटन द्वारा शो के संवाद को क्लिक करने की कोशिश की है।

            FragmentManager fm = getSupportFragmentManager();
            Fragment oldFragment = fm.findFragmentByTag("wait_modal");

            if(oldFragment != null && oldFragment.isAdded())
                return;

            if(oldFragment == null && !please_wait_modal.isAdded() && !please_wait_modal.isVisible()){
                fm.executePendingTransactions();
                please_wait_modal.show(fm,"wait_modal");
            }
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.