java.lang.IllegalStateException: फ्रैगमेंट एक्टिविटी से जुड़ी नहीं है


148

एपीआई कॉल करते समय मुझे यह त्रुटि शायद ही कभी मिल रही हो।

java.lang.IllegalStateException: Fragment  not attached to Activity

मैंने isAdded()यह जांचने के लिए कोड को विधि के अंदर रखने का प्रयास किया कि क्या वर्तमान में इसकी गतिविधि में टुकड़ा जोड़ा गया है, लेकिन फिर भी मुझे शायद ही कभी यह त्रुटि मिलती है। मैं यह समझने में विफल हूं कि मुझे अभी भी यह त्रुटि क्यों हो रही है। मैं यह कैसे रोक सकता हूँ?

लाइन पर अपनी त्रुटि दिखा रहा है-

cameraInfo.setId(getResources().getString(R.string.camera_id));

नीचे नमूना एपी कॉल है जिसे मैं बना रहा हूं।

SAPI.getInfo(getActivity(),
                new APIResponseListener() {
                    @Override
                    public void onResponse(Object response) {


                        cameraInfo = new SInfo();
                        if(isAdded()) {
                            cameraInfo.setId(getResources().getString(R.string.camera_id));
                            cameraInfo.setName(getResources().getString(R.string.camera_name));
                            cameraInfo.setColor(getResources().getString(R.string.camera_color));
                            cameraInfo.setEnabled(true);
                        }


                    }

                    @Override
                    public void onError(VolleyError error) {
                        mProgressDialog.setVisibility(View.GONE);
                        if (error instanceof NoConnectionError) {
                            String errormsg = getResources().getString(R.string.no_internet_error_msg);
                            Toast.makeText(getActivity(), errormsg, Toast.LENGTH_LONG).show();
                        }
                    }
                });

cameraInfo.setId (।। getActivity () getResources () GetString (R.string.camera_id));
अश्विन H

जवाबों:


203

यह त्रुटि दो कारकों के संयुक्त प्रभाव के कारण होती है:

  • HTTP अनुरोध, जब पूरा हो जाता है, onResponse()या तो या onError()(जो मुख्य थ्रेड पर काम करता है) यह जाने बिना कि क्या Activityअभी भी अग्रभूमि में है या नहीं है , को आमंत्रित करता है । यदि Activityचला गया है (उपयोगकर्ता ने कहीं और नेविगेट किया है), getActivity()शून्य देता है।
  • वॉली Responseको एक गुमनाम आंतरिक वर्ग के रूप में व्यक्त किया जाता है, जो बाहरी Activityवर्ग के लिए एक मजबूत संदर्भ रखता है । यह एक क्लासिक मेमोरी लीक में परिणाम है।

इस समस्या को हल करने के लिए, आपको हमेशा करना चाहिए:

Activity activity = getActivity();
if(activity != null){

    // etc ...

}

और भी, विधि isAdded()में भी उपयोग करें onError():

@Override
public void onError(VolleyError error) {

    Activity activity = getActivity(); 
    if(activity != null && isAdded())
        mProgressDialog.setVisibility(View.GONE);
        if (error instanceof NoConnectionError) {
           String errormsg = getResources().getString(R.string.no_internet_error_msg);
           Toast.makeText(activity, errormsg, Toast.LENGTH_LONG).show();
        }
    }
}

2
वॉली के अनुरोधों का उपयोग करते हुए और ए के AsyncTaskभीतर से Activity, एनपीई से बचने के लिए कोई मूर्खतापूर्ण तरीका नहीं है। वहाँ हमेशा मौका है कि उपयोगकर्ता वर्तमान से अन्यत्र जा सकता है Activity, जबकि धागे में से एक पृष्ठभूमि में कुछ कर रहा है, और फिर धागा पूरा करता है और जब onPostExecute()या onResponse()कहा जाता है, वहाँ कोई है Activity। आप सभी अपने कोड में विभिन्न बिंदुओं पर अशक्त संदर्भों के लिए चेक बना सकते हैं, और यह बुलेटप्रूफ नहीं है :)
YS

2
यदि आप पहले से ही एक सामान्य या वैश्विक फैशन में इसका हिसाब नहीं रखते हैं, तो एंड्रॉइड मंकी टेस्ट (अदब शेल बंदर) वास्तव में इस त्रुटि को दूर करने में अच्छा है।
Groovee60

5
isAdded () पर्याप्त है, अंतिम सार्वजनिक बूलियन AdAdded () {रिटर्न mActivity! = null && mAdded; }
lannyf

2
@ruselli: addedबूलियन ध्वज की जाँच करता है और वर्तमान Activityआवृत्ति है nullया नहीं।
YS

1
@gauravjain फ़्रैगमेंट से सीधे एसिंक्रोनस अनुरोध (जैसे HTTP कॉल) करने से बचें। इसे गतिविधि से करें और यह ठीक होना चाहिए। इसके अलावा, FragmentManager से स्पष्ट फ़्रैगमेंट संदर्भ, यह एक अच्छा अभ्यास है और मेमोरी लीक से बचने का सबसे अच्छा तरीका है।
वाईएस

56

फ्रैगमेंट जीवनचक्र बहुत जटिल और बग से भरा हुआ है, इसे जोड़ने की कोशिश करें:

Activity activity = getActivity(); 
if (isAdded() && activity != null) {
...
}

2
मैं इसे कहां रखूं?
वेकलोव्स रेकासियस जूनियर

1
@ VaclovasRekašiusJr। लगता है कि कहीं भी आप खंड के अंदर से गतिविधि का उपयोग करना चाहते हैं। आनंद!
टायलरजाम्स

2
गतिविधि == अशक्त होने पर मुझे क्या करना चाहिए अपने आवेदन @Miroslav जीवित रखने के लिए
पावेल

IsAdded में देखें () , आपको "गतिविधि मिल सकती है! =
Null

@BertKing return mHost != null && mAdded;- यह है कि अंदर क्या टुकड़ा .isAdded () विधि। मैंने सोचा था कि यदि आप इसे ट्रेस करते हैं तो mHost एक गतिविधि है, लेकिन ऐसा लगता है कि mHost FragmentActivity के अंदर है। तो, शायद, आप सही हैं। कोई जोड़?
जॉनी फाइव

14

मैंने पाया बहुत ही सरल समाधान एडेड () विधि है जो यह पहचानने के लिए कि यह वर्तमान टुकड़ा इसके गतिविधि से जुड़ा हुआ है या नहीं, इसकी एक विधि है।

हम इसका उपयोग हर जगह टुकड़े की तरह कर सकते हैं जैसे:

if(isAdded())
{

// using this method, we can do whatever we want which will prevent   **java.lang.IllegalStateException: Fragment not attached to Activity** exception.

}

12

अपवाद: java.lang.IllegalStateException: टुकड़ा

डेडलाइन लिस्टग्रैगमेंट {ad2ef970} गतिविधि से जुड़ा नहीं है

श्रेणी: जीवनचक्र

विवरण : बैकग्राउंड थ्रेड (जैसे, AsyncTask) में समय लेने वाली कार्रवाई करते समय, इस बीच एक नया फ़्रैगमेंट बनाया गया है, और बैकग्राउंड थ्रेड समाप्त होने से पहले गतिविधि के लिए अलग कर दिया गया था। UI थ्रेड में कोड (जैसे, onPostExecute) एक अलग फ्रैगमेंट पर कॉल करता है, इस तरह के अपवाद को फेंक देता है।

समाधान ठीक करें:

  1. विराम चिह्न या विराम रोकते समय पृष्ठभूमि थ्रेड रद्द करें

  2. टुकड़ा जुड़ा हुआ है और फिर गतिविधि से getResources () है या नहीं, यह जांचने के लिए .Added () का उपयोग करें।


11

मुझे देर हो सकती है लेकिन किसी की मदद कर सकते हैं ..... इसके लिए सबसे अच्छा उपाय यह है कि आप एक वैश्विक एप्लिकेशन क्लास इंस्टेंस बनाएं और इसे उस विशेष खंड में कॉल करें जहां आपकी गतिविधि संलग्न नहीं हो रही है

नीचे की तरह

icon = MyApplication.getInstance().getString(R.string.weather_thunder);

यहाँ एप्लिकेशन क्लास है

public class MyApplication extends Application {

    private static MyApplication mInstance;
    private RequestQueue mRequestQueue;

    @Override
    public void onCreate() {
        super.onCreate();
        mInstance = this;
    }

    public static synchronized MyApplication getInstance() {
        return mInstance;
    }
}

1
हां, इस विधि का भी व्यापक रूप से उपयोग किया जाता है।
कूलमाइंड

1
यह बुद्धिमान विकल्प नहीं है। FragmentContext और ApplicationContext की अलग-अलग शैलियाँ हैं। Fragment Context में डार्क थीम, कस्टम स्टाइल, लोकेल आदि हो सकते हैं .. जो विभिन्न फाइलों से रंग, स्ट्रिंग संसाधनों को खींचेंगे। जबकि ApplicationContext सही संसाधन नहीं खींच सकता है। यदि आपके पास संदर्भ नहीं है, तो आपको उस संसाधन को प्रस्तुत करने की कोशिश नहीं करनी चाहिए।
जेमसहित इस्केंडरोव

2

यह त्रुटि तब हो सकती है जब आप किसी ऐसे टुकड़े को तात्कालिक कर रहे हैं जो किसी भी तरह त्वरित नहीं हो सकता है:

Fragment myFragment = MyFragment.NewInstance();


public classs MyFragment extends Fragment {
  public void onCreate() {
   // Some error here, or anywhere inside the class is preventing it from being instantiated
  }
}

मेरे मामले में, जब मैंने इसका उपयोग करने की कोशिश की, तो मैं इससे मिला:

private String loading = getString(R.string.loading);

2

खुशबू उपयोग में isAdded() यह सच हो जाएगा अगर टुकड़ा वर्तमान में गतिविधि से जुड़ा हुआ है।

यदि आप गतिविधि के अंदर जांचना चाहते हैं

 Fragment fragment = new MyFragment();
   if(fragment.getActivity()!=null)
      { // your code here}
      else{
       //do something
       }

आशा है कि यह किसी की मदद करेगा


1

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

public class ContextWrapper {
    public static String getString(Activity activity, int resourceId, String defaultValue) {
        if (activity != null) {
            return activity.getString(resourceId);
        } else {
            return defaultValue;
        }
    }

    //similar methods like getDrawable(), getResources() etc

}

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

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


0

यह तब होता है जब टुकड़े का कोई संदर्भ नहीं होता है, इस प्रकार getActivity () विधि वापस शून्य हो जाती है। जाँच करें कि क्या आप संदर्भ का उपयोग करने से पहले इसे context या यदि गतिविधि मौजूद नहीं है। संदर्भ में संदर्भ का उपयोग करें। फिर से बनाएं और एपीआई प्रतिक्रिया के बाद आमतौर पर इस समस्या का मामला बनता है


0

कभी-कभी यह अपवाद समर्थन लाइब्रेरी कार्यान्वयन में बग के कारण होता है। हाल ही में मुझे इससे छुटकारा पाने के लिए 26.1.0 से 25.4.0 तक नीचे जाना पड़ा।


नहीं, मैं नहीं, लेकिन शायद मुझे एक बनाना चाहिए।
बॉर्ड81

0

यह समस्या तब होती है जब आप एक संदर्भ को कॉल करते हैं जो अनुपलब्ध या अशक्त होता है। यह एक ऐसी स्थिति हो सकती है जब आप मुख्य गतिविधि थ्रेड के संदर्भ को बैकग्राउंड थ्रेड या बैकग्राउंड थ्रेड के संदर्भ को मुख्य गतिविधि थ्रेड पर बुला रहे हैं।

उदाहरण के लिए, मैंने अपनी साझा प्राथमिकता स्ट्रिंग को निम्नलिखित की तरह अद्यतन किया।

editor.putString("penname",penNameEditeText.getText().toString());
editor.commit();
finish();

और इसके ठीक बाद खत्म () कहा जाता है। अब यह क्या करता है कि जैसा कि प्रतिबद्ध मुख्य धागे पर चलता है और समाप्त होने तक आने वाले किसी भी अन्य एसिक्स को रोकता है। इसलिए इसका संदर्भ तब तक जीवित है जब तक कि लेखन पूरा न हो जाए। इसलिए पिछला संदर्भ लाइव है, जिससे त्रुटि उत्पन्न होती है।

तो यह सुनिश्चित करें कि इस संदर्भ समस्या होने पर कुछ कोड होने पर अपने कोड को फिर से जाँच लें।


आपने इस समस्या को कैसे ठीक किया? मैं इसे एक async थ्रेड के भीतर कॉल कर रहा हूं और अब इस समस्या का अनुभव कर रहा हूं।
सिमोन

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