Ich habe dieses Muster ein wenig benutzt. Hier ist ein sehr gelungenes Beispiel für eine AsyncTask + Fortschrittsanzeige:
%Vor%Es funktioniert gut mit Orientierungsänderungen, aber ich habe festgestellt, dass das Fragment nicht null ist und fragment.getView () null ist, wenn ich das Fragment aus dem Backstack entferne. Das verursacht offensichtlich einen Absturz. Welchen Ansatz verwenden Sie? Ich kann nicht scheinen, eine vollkommene Lösung online zu finden. Wichtiger Hinweis, dies ist in einem Fragment und ich rufe %code% für dieses Fragment in seiner onActivityCreated (...).
auf%code% ist eine asynchrone Aufgabe, was bedeutet, dass Sie normalerweise nicht wissen, wann sie abgeschlossen ist und wann sie %code% aufruft. Ich denke, dein Problem ist hier. Wenn Sie Ihr Gerät drehen, ist Ihre asynctask noch nicht beendet und Ihre Fragmentansicht ist zerstört und wird sehr schnell neu erstellt, während sich asynctask auf dem Arbeitsthread befindet und wenn es seine Aufgabe erledigt hat, hat Ihr Fragment eine Sicht und %code% 's Rückgabewert ist nicht %code% . Wenn die Rotationszeit jedoch viel Zeit in Anspruch nimmt, erhalten Sie %code% , weil %code% beendet ist, aber Ihr Fragment keine Sicht hat. Dieses Szenario passiert nun genau mit deinem Backstack. Wenn du dein Fragment auf den Backstack drückst, wird seine Ansicht zerstört (schau ) auf dem Bild ), aber das Fragment selbst ist nicht (das Fragment kehrt vom Backstack zum Layout zurück). Jetzt ist Ihre %code% fertig und rufen Sie Ihre %code% %code% -Methode auf und sie hat keine %code% , so dass Sie %code% erhalten.
Meine Lösung:
Zuerst sollten Sie %code% anstelle von %code% verwenden und in %code% überprüfen, ob es null ist oder nicht, wenn es null ist, nichts tun, weil der Standardwert unsichtbar ist, wenn es nicht null ist Aufruf %code% .
Aktualisierung:
Das Fragment ist am Leben, aber die Ansicht wurde freigegeben. Ist das möglich?
Ja, sehen Sie sich die Abbildung2 vom Link an. Wenn das Fragment aktiv ist (grünes Feld), wird %code% Fragment zu %code% , %code% onDestroyView . Wenn das Fragment dann aus dem Back-Stack herausspringt, geht es direkt zu %code% der Pfeil-Verknüpfung mit diesem Text: %code% .
Um meine Antwort zu bestätigen, können Sie ein %code% erstellen und %code% in Ihrem %code% aufrufen. Jetzt können Sie Ihr Fragment in den Backstack schieben und es aus dem Backstack ohne Ausnahme aufheben, da die asynctask nicht beendet ist und wenn Sie %code% aufrufen, hat Ihr Fragment bereits eine View.
Eine weitere gute Sache, die Sie sehen können, ist setRetainInstance
Dies kann nur mit Fragmenten verwendet werden, die sich nicht im Backstack befinden.
Wenn Sie also Ihr Fragment in den Backstack schieben, kann vollständig zerstört werden und Sie erhalten eine neue Fragmentreferenz, wenn sie auftaucht. Wenn Sie jedoch %code% für Konfigurationsänderungen verwenden, wird Ihr Fragment bei der erneuten Erstellung von Aktivitäten beibehalten , dh es ist das gleiche Fragment und %code% wird nicht aufgerufen. Und das ist eine sehr sehr wichtige Sache, denn wenn Sie Ihr %code% bei der Methode %code% starten, wenn Sie Ihr Fragment in den Backstack schieben und es aufklappen, können Sie ein neues Fragment haben und Das bedeutet %code% Methode läuft und ein weiterer %code% wird ausgelöst. Das heißt, Sie haben keine Kontrolle über die Anzahl der Aufrufenden %code% s. Achten Sie also darauf Speicherlecks!
Ich habe dieses Muster ein wenig benutzt. Hier ist ein sehr gelungenes Beispiel für eine AsyncTask + Fortschrittsanzeige:
%Vor% Es funktioniert gut mit Orientierungsänderungen, aber ich habe festgestellt, dass das Fragment nicht null ist und fragment.getView () null ist, wenn ich das Fragment aus dem Backstack entferne. Das verursacht offensichtlich einen Absturz. Welchen Ansatz verwenden Sie? Ich kann nicht scheinen, eine vollkommene Lösung online zu finden. Wichtiger Hinweis, dies ist in einem Fragment und ich rufe setRetainInstance(true);
für dieses Fragment in seiner onActivityCreated (...).
AsyncTask
ist eine asynchrone Aufgabe, was bedeutet, dass Sie normalerweise nicht wissen, wann sie abgeschlossen ist und wann sie onPostExecute()
aufruft. Ich denke, dein Problem ist hier. Wenn Sie Ihr Gerät drehen, ist Ihre asynctask noch nicht beendet und Ihre Fragmentansicht ist zerstört und wird sehr schnell neu erstellt, während sich asynctask auf dem Arbeitsthread befindet und wenn es seine Aufgabe erledigt hat, hat Ihr Fragment eine Sicht und getView
's Rückgabewert ist nicht null
. Wenn die Rotationszeit jedoch viel Zeit in Anspruch nimmt, erhalten Sie null
, weil AsyncTask
beendet ist, aber Ihr Fragment keine Sicht hat. Dieses Szenario passiert nun genau mit deinem Backstack. Wenn du dein Fragment auf den Backstack drückst, wird seine Ansicht zerstört (schau ) auf dem Bild ), aber das Fragment selbst ist nicht (das Fragment kehrt vom Backstack zum Layout zurück). Jetzt ist Ihre AsyncTask
fertig und rufen Sie Ihre fragment
getView
-Methode auf und sie hat keine view
, so dass Sie NPE
erhalten.
Meine Lösung:
Zuerst sollten Sie WeakReference<ProgressBar>
anstelle von WeakReference<MyFragment>
verwenden und in onPostExecute()
überprüfen, ob es null ist oder nicht, wenn es null ist, nichts tun, weil der Standardwert unsichtbar ist, wenn es nicht null ist Aufruf setVisibility(View.GONE)
.
Aktualisierung:
Das Fragment ist am Leben, aber die Ansicht wurde freigegeben. Ist das möglich?
Ja, sehen Sie sich die Abbildung2 vom Link an. Wenn das Fragment aktiv ist (grünes Feld), wird the fragment added to back stack
Fragment zu onPause
, onStop
onDestroyView . Wenn das Fragment dann aus dem Back-Stack herausspringt, geht es direkt zu onCreateView
der Pfeil-Verknüpfung mit diesem Text: the fragment returns to the layout from backstack
.
Um meine Antwort zu bestätigen, können Sie ein AsyncTask
erstellen und SystemClock.sleep(30000)
in Ihrem doInbackground
aufrufen. Jetzt können Sie Ihr Fragment in den Backstack schieben und es aus dem Backstack ohne Ausnahme aufheben, da die asynctask nicht beendet ist und wenn Sie onPostExecute()
aufrufen, hat Ihr Fragment bereits eine View.
Eine weitere gute Sache, die Sie sehen können, ist setRetainInstance
Dies kann nur mit Fragmenten verwendet werden, die sich nicht im Backstack befinden.
Wenn Sie also Ihr Fragment in den Backstack schieben, kann vollständig zerstört werden und Sie erhalten eine neue Fragmentreferenz, wenn sie auftaucht. Wenn Sie jedoch setRetainInstance(true);
für Konfigurationsänderungen verwenden, wird Ihr Fragment bei der erneuten Erstellung von Aktivitäten beibehalten , dh es ist das gleiche Fragment und onCreate
wird nicht aufgerufen. Und das ist eine sehr sehr wichtige Sache, denn wenn Sie Ihr AsyncTask
bei der Methode onCreate
starten, wenn Sie Ihr Fragment in den Backstack schieben und es aufklappen, können Sie ein neues Fragment haben und Das bedeutet onCreate
Methode läuft und ein weiterer AsyncTask
wird ausgelöst. Das heißt, Sie haben keine Kontrolle über die Anzahl der Aufrufenden AsyncTask
s. Achten Sie also darauf
Speicherlecks!
Tags und Links android android-asynctask android-fragments progress-bar