Mein Problem beinhaltet eine Aktivität, die drei Supportfragmente enthält. Einer ist ein normales programmatisches Fragment (nennen wir es ein Home-Fragment). Das eine ist ein Porträtfragment, das auf dem Hauptfragment hinzugefügt wird, wenn das Gerät ausgerichtet ist, und das andere ist "kopflos", um unabhängig von Konfigurationsänderungen eine asynchrone Aufgabe fortzusetzen. Sehr einfach, ich arbeitete an diesem netten Beispiel .
%Vor%}
In meiner Aktivität onCreate () erstelle ich das kopflose Fragment und füge es bei Bedarf hinzu.
%Vor%Ich starte dann eine asynchrone Aufgabe (über meine startFetching () -Funktion) nach einer Verzögerung von 6 Sekunden (zum Testen), die in der onCreateView () des Porträtfragments ausgelöst wurde, das hinzugefügt wird, wenn sich die Ausrichtung in Hochformat ändert. Die Orientierungsänderung wird in der Aktivität onCreate () der Aktivität erkannt:
%Vor%Nach Abschluss der Aufgabe kehre ich zur Aktivität zurück und versuche, die Benutzeroberfläche des aktiven Hochformatfragments zu aktualisieren. Der Fragmentmanager kann sie jedoch nicht finden. findFragmentByTag () gibt null zurück.
Um es klar zu sagen:
Vielleicht werden durch das Beibehalten eines Fragments aggressiv andere Fragmente, die nicht beibehalten werden, oder etwas in diesem Sinne getötet?
Die Wurzel des Problems besteht darin, wie Sie den Verweis auf die Aktivität innerhalb des kopflosen Fragments beibehalten.
Aus dem bereitgestellten Code geht nicht hervor, wie Sie die Benutzeroberfläche nach Abschluss von AsyncTask aktualisieren. Nehmen wir an, Sie verwenden mRequest
aus dem ersten Code-Snippet. Sie geben mRequest
an den Konstruktor an, wenn Sie eine neue AsyncTask benötigen und diese Referenz verwenden, nachdem AsyncTask abgeschlossen ist.
Es ist in Ordnung, wenn zwischen dem Zeitpunkt der Erstellung der Aktivität und der Aktualisierung der Benutzeroberfläche keine Bildschirmdrehung erfolgt. Dies liegt daran, dass Sie den Verweis auf die noch aktive Aktivität verwenden.
Es ist nicht in Ordnung, wenn Sie den Bildschirm drehen. Sie haben jedes Mal nach der Rotation neue Aktivitäten. Aber mRequest wird nur einmal zugewiesen, wenn Sie ein kopfloses Fragment beim ersten Aufruf von onCreate()
der Aktivität erstellen. Es enthält also eine Referenz auf die erste Instanz der Aktivität, die nach der Rotation nicht aktiv ist. Es gibt zwei Fälle von Aktivität nach Rotation in Ihrem Fall: der erste - der von mRequest referenziert wird und der zweite - der sichtbar und aktiv ist. Sie können dies bestätigen, indem Sie die Referenz der Aktivität in onCreate
: Log.i(TAG, "onCreate: this=" + this);
und die Methode der internen Aktivität protokollieren, die die Benutzeroberfläche nach der asynchronen Task aktualisiert: Log.i(TAG, "updating UI: this=" + this);
Außerdem ist die erste Aktivität im Zerstörten Zustand. Alle Fragmente werden von dieser Aktivität abgelöst und nicht zurückgehaltene Fragmente werden zerstört. Deshalb gibt findFragmentByTag
null zurück.
Wenn das kopflose Fragment nicht auf sich selbst festgelegt ist, wird es in onCreate()
der Aktivität bei jedem Aufruf neu erstellt. So verweist mRequest
immer auf die zuletzt erstellte Aktivität mit allen Fragmenten. In diesem Fall gibt findFragmentByTag
nicht null zurück
Um dieses Problem zu vermeiden, schlage ich vor:
private WeakReference<RequestCustomerDetails> mRequest;
HeadlessCustomerDetailFetchFragment
, um diese Referenz zu aktualisieren. public void updateResultProcessor(RequestCustomerDetails requestCustomerDetails) {
mRequest = new WeakReference(requestCustomerDetails);
// Update ui if there is stored result of AsyncTask (see p.4b)
}
mRequest.get()
nicht null
ist, update UI. mRequest.get()
ist null
, dann speichern Sie das Ergebnis innerhalb des Headless-Fragments und verwenden Sie es in S.2
Eine schwache Referenz ermöglicht es GC, zerstörte Aktivität zu verarbeiten und null innerhalb einer schwachen Referenz zu setzen. Null innerhalb der schwachen Referenz signalisiert, dass es keine Benutzeroberfläche gibt und nichts zu aktualisieren ist. Das Speichern des Ergebnisses von AsyncTask in einem kopflosen Fragment ermöglicht es, dieses Ergebnis zu verwenden, um die Benutzeroberfläche nach ihrer Wiederherstellung zu aktualisieren.
Tags und Links android android-fragments android-configchanges android-fragmentmanager