Ich erhalte diesen Fehler selten während eines API-Aufrufs.
Java.lang.IllegalStateException: Fragment not attached to Activity
Ich habe versucht, den Code in die isAdded()
-Methode zu setzen, um zu prüfen, ob das Fragment derzeit zu seiner Aktivität hinzugefügt wird, aber ich bekomme diesen Fehler selten. Ich kann nicht verstehen, warum ich diesen Fehler immer noch bekomme. Wie kann ich das verhindern?
Sein Fehler auf der Leitung
cameraInfo.setId(getResources().getString(R.string.camera_id));
Unten ist der Beispiel-API-Aufruf, den ich mache.
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();
}
}
});
Dieser Fehler tritt aufgrund des kombinierten Effekts zweier Faktoren auf:
onResponse()
oder onError()
(die im Hauptthread funktionieren) auf, ohne zu wissen, ob sich Activity
noch im Vordergrund befindet. Wenn Activity
nicht mehr vorhanden ist (der Benutzer ist an anderer Stelle navigiert), gibt getActivity()
den Wert null zurück.Response
wird als anonyme innere Klasse ausgedrückt, die implizit einen starken Verweis auf die äußere Klasse Activity
enthält. Dies führt zu einem klassischen Speicherverlust.Um dieses Problem zu lösen, sollten Sie immer Folgendes tun:
Activity activity = getActivity();
if(activity != null){
// etc ...
}
verwenden Sie isAdded()
auch in der 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();
}
}
}
Der Fragment-Lebenszyklus ist sehr komplex und voller Fehler.
Activity activity = getActivity();
if (isAdded() && activity != null) {
...
}
Ich habe eine sehr einfache Lösung gefunden isAdded () - Methode, eine der Fragment-Methoden, um zu identifizieren, ob dieses aktuelle Fragment an seine Aktivität angehängt ist oder nicht.
wir können dies wie überall in der Fragmentklasse verwenden:
if(isAdded())
{
// using this method, we can do whatever we want which will prevent **Java.lang.IllegalStateException: Fragment not attached to Activity** exception.
}
Ausnahme: Java.lang.IllegalStateException: Fragment
DeadlineListFragment {ad2ef970} nicht an Aktivität angehängt
Kategorie: Lebenszyklus
Beschreibung : Bei der zeitaufwändigen Operation im Hintergrundthread (z. B. AsyncTask) wurde in der Zwischenzeit ein neues Fragment erstellt und vor dem Abschluss des Hintergrundthreads von der Aktivität getrennt. Der Code im UI-Thread (z. B. onPostExecute) ruft ein getrenntes Fragment auf und löst eine solche Ausnahme aus.
Lösung beheben:
Brechen Sie den Hintergrund-Thread ab, wenn Sie das -Fragment anhalten oder stoppen
Verwenden Sie isAdded (), um zu prüfen, ob das Fragment Angehängt ist, und dann für getResources () aus der Aktivität.
ich komme möglicherweise zu spät, kann aber jemandem helfen. Die beste Lösung dafür ist, eine globale Anwendungsklasseninstanz zu erstellen und sie in einem bestimmten Fragment aufzurufen, an dem Ihre Aktivität nicht angehängt wird
wie unten
icon = MyApplication.getInstance().getString(R.string.weather_thunder);
Hier ist die Anwendungsklasse
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;
}
}
Dieser Fehler kann auftreten, wenn Sie ein Fragment instanziieren, das irgendwie nicht instanziiert werden kann:
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 meinem Fall habe ich dies getroffen, als ich versuchte zu verwenden:
private String loading = getString(R.string.loading);
In Fragment verwenden Sie isAdded()
Es wird true zurückgegeben, wenn das Fragment aktuell an Activity angehängt ist.
Wenn Sie die Aktivität überprüfen möchten
Fragment fragment = new MyFragment();
if(fragment.getActivity()!=null)
{ // your code here}
else{
//do something
}
Ich hoffe es hilft jemandem
Ich habe den folgenden Ansatz gewählt, um dieses Problem zu behandeln. Erstellt eine neue Klasse, die als Wrapper für Aktivitätsmethoden wie diese fungiert
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
}
Wo immer ich auf Ressourcen aus Fragmenten oder Aktivitäten zugreifen muss, anstatt die Methode direkt aufzurufen, verwende ich diese Klasse. Falls die Aktivität context
nicht null
ist, gibt sie den Wert des Assets zurück, und falls context
null ist, übergibt sie einen Standardwert (der auch vom Aufrufer der Funktion angegeben wird).
Wichtig Dies ist keine Lösung, dies ist ein effektiver Weg, um diesen Absturz elegant zu handhaben. Sie möchten einige Protokolle hinzufügen, wenn Sie die Aktivitätsinstanz als null erhalten und versuchen, dies zu beheben, falls dies möglich ist.
Dieses Problem tritt immer dann auf, wenn Sie einen Kontext aufrufen, der beim Aufruf nicht verfügbar oder null ist. Dies kann eine Situation sein, wenn Sie den Kontext des Hauptaktivitätsthreads in einem Hintergrundthread oder den Kontext des Hintergrundthreads im Hauptaktivitätsthread aufrufen.
Zum Beispiel habe ich meine freigegebene Einstellungszeichenfolge wie folgt aktualisiert.
editor.putString("penname",penNameEditeText.getText().toString());
editor.commit();
finish();
Und rief direkt nach ihm finish () an. Nun ist es so, dass Commit im Haupt-Thread ausgeführt wird und alle anderen Async-Commits angehalten werden, wenn sie kommen, bis der Vorgang abgeschlossen ist. Der Kontext ist also lebendig, bis der Schreibvorgang abgeschlossen ist. Daher ist der vorherige Kontext live, wodurch der Fehler auftritt.
Stellen Sie daher sicher, dass Ihr Code erneut überprüft wird, wenn Code mit diesem Kontextproblem vorliegt.
Manchmal wird diese Ausnahme durch einen Fehler in der Implementierung der Unterstützungsbibliothek verursacht. Vor kurzem musste ich von 26.1.0 auf 25.4.0 herabstufen, um es loszuwerden.
dies geschieht, wenn das Fragment keinen Kontext hat. Die Methode getActivity () gibt also null zurück. Prüfen Sie, ob Sie den Kontext verwenden, bevor Sie ihn abrufen, oder ob die Aktivität nicht mehr vorhanden ist. Verwenden Sie den Kontext in fragment.onCreate und nach einer API-Antwort normalerweise dieses Problem