java.lang.IllegalStateException: fragment niet gekoppeld aan activiteit

Ik krijg deze foutmelding zelden wanneer ik een API-aanroep doe.

java.lang.IllegalStateException: Fragment  not attached to Activity

Ik heb geprobeerd de code in de isAdded()-methode te plaatsen om te controleren of het fragment momenteel aan zijn activiteit is toegevoegd, maar ik krijg deze foutmelding nog steeds zelden. Ik begrijp niet waarom ik nog steeds deze foutmelding krijg. Hoe kan ik het voorkomen?

Er wordt een fout weergegeven op de regel-

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

Hieronder staat de voorbeeld-API-aanroep die ik aan het maken ben.

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();
                        }
                    }
                });

Antwoord 1, autoriteit 100%

Deze fout treedt op vanwege het gecombineerde effect van twee factoren:

  • Het HTTP-verzoek roept, wanneer voltooid, onResponse()of onError()aan (die werken op de hoofdthread) zonder te weten of de Activitystaat nog steeds op de voorgrond of niet. Als de Activityverdwenen is (de gebruiker heeft ergens anders genavigeerd), retourneert getActivity()null.
  • De Volley Responsewordt uitgedrukt als een anonieme innerlijke klasse, die impliciet een sterke verwijzing bevat naar de buitenste Activity-klasse. Dit resulteert in een klassiek geheugenlek.

Om dit probleem op te lossen, moet u altijd het volgende doen:

Activity activity = getActivity();
if(activity != null){
    // etc ...
}

en gebruik ook isAdded()in de onError()methode:

@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();
        }
    }
}

Antwoord 2, autoriteit 30%

De levenscyclus van fragment is erg complex en zit vol met bugs, probeer toe te voegen:

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

Antwoord 3, autoriteit 9%

Ik vond een zeer eenvoudige oplossing isAdded()methode die een van de fragmentmethodes is om te identificeren of dit huidige fragment al dan niet aan zijn Activiteit is gekoppeld.

we kunnen dit overal in de fragmentklasse gebruiken zoals:

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

Antwoord 4, autoriteit 7%

Uitzondering:java.lang.IllegalStateException: Fragment

DeadlineListFragment{ad2ef970} niet gekoppeld aan activiteit

Categorie:Levenscyclus

Beschrijving: bij het uitvoeren van tijdrovende bewerkingen in de achtergrondthread (bijv. AsyncTask), is in de tussentijd een nieuw fragment gemaakt en losgekoppeld van de activiteit voordat de achtergrondthread was voltooid. De code in de UI-thread (bijv. onPostExecute) roept een losstaand fragment aan en veroorzaakt zo’n uitzondering.

Oplossing oplossen:

  1. Annuleer de achtergrondthread bij het pauzeren of stoppen van de
    Fragment

  2. Gebruik isAdded() om te controleren of het fragment is bijgevoegd
    en vervolgens naar getResources() van activiteit.


Antwoord 5, autoriteit 5%

Ik ben misschien te laat maar kan iemand helpen …..
De beste oplossing hiervoor is om een ​​globale applicatieklasse-instantie te maken en deze aan te roepen in het specifieke fragment waaraan uw activiteit niet wordt gekoppeld

zoals hieronder

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

Hier is de toepassingsklasse

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;
    }
}

Antwoord 6, autoriteit 2%

Gebruik in Fragment isAdded()
Het zal true retourneren als het fragment momenteel is gekoppeld aan Activiteit.

Als je in de Activiteit wilt kijken

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

Ik hoop dat het iemand zal helpen


Antwoord 7

Deze fout kan optreden als u een fragment aan het instantiëren bent dat op de een of andere manier niet kan worden geïnstantieerd:

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
  }
}

In mijn geval ben ik dit tegengekomen toen ik probeerde te gebruiken:

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

Antwoord 8

Ik heb de volgende aanpak gevolgd om dit probleem op te lossen. Een nieuwe klasse gemaakt die fungeert als een wrapper voor activiteitsmethoden zoals deze

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
}

Overal waar ik bronnen van fragmenten of activiteiten nodig heb, in plaats van de methode rechtstreeks aan te roepen, gebruik ik deze klasse. Als de activiteit contextniet nullis, wordt de waarde van het item geretourneerd en als de contextnull is, wordt een standaardwaarde doorgegeven ( die ook wordt gespecificeerd door de aanroeper van de functie).

BelangrijkDit is geen oplossing, dit is een effectieve manier om deze crash gracieus af te handelen. U zou enkele logboeken willen toevoegen in gevallen waarin u een activiteitsinstantie als null krijgt en proberen dit indien mogelijk op te lossen.


Antwoord 9

Het basisidee is dus dat u een UI-bewerkinguitvoert op een fragment dat in de onDetach-levenscyclus komt.

Als dit gebeurt, raakt het fragment van de stapel en verliest het de context van de Activiteit.

Dus als je UI-gerelateerde functies aanroept, bijvoorbeeld de voortgangsspinner aanroepen en je het fragment wilt verlaten, controleer dan of het fragment aan de stapel is toegevoegd, zoals dit:

if(isAdded){ progressBar.visibility=View.VISIBLE }


Antwoord 10

dit gebeurt wanneer het fragment geen context heeft, dus de getActivity()methode retourneert null.
controleer of je de context gebruikt voordat je het krijgt, of dat de Activiteit niet meer bestaat. gebruik context in fragment.onCreate en na api-reactie meestal dit probleem


Antwoord 11

Soms wordt deze uitzondering veroorzaakt door een fout in de implementatie van de ondersteuningsbibliotheek. Onlangs moest ik downgraden van 26.1.0 naar 25.4.0 om er vanaf te komen.


Antwoord 12

Dit probleem doet zich voor wanneer u een context oproept die niet beschikbaar is of nul is wanneer u deze oproept. Dit kan een situatie zijn wanneer u de context van de hoofdactiviteitsthread oproept op een achtergrondthread of de context van de achtergrondthread op de hoofdactiviteitthread.

Ik heb bijvoorbeeld mijn string met gedeelde voorkeuren bijgewerkt, zoals hieronder.

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

En direct daarna finish() genoemd. Wat het nu doet, is dat als commit wordt uitgevoerd op de hoofdthread en alle andere Async-commits worden gestopt als ze komen totdat het klaar is. Dus de context is levend totdat het schrijven is voltooid. Vandaar dat de vorige context live is, waardoor de fout optreedt.

Zorg er dus voor dat uw code opnieuw wordt gecontroleerd als er een code is met dit contextprobleem.

Other episodes