Ich habe viele Beispiele für eine ähnliche Frage zu SO gefunden, aber leider entspricht keine Antwort meinen Anforderungen.
Ich habe unterschiedliche Layouts für Hoch- und Querformat und verwende einen Backstack, der mich daran hindert setRetainState()
, Konfigurationsänderungsroutinen zu verwenden, und Tricks verwendet.
Ich zeige dem Benutzer bestimmte Informationen in TextViews an, die nicht im Standardhandler gespeichert werden. Beim Schreiben meiner Bewerbung ausschließlich mit Aktivitäten hat Folgendes gut funktioniert:
TextView vstup;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.whatever);
vstup = (TextView)findViewById(R.id.whatever);
/* (...) */
}
@Override
public void onSaveInstanceState(Bundle state) {
super.onSaveInstanceState(state);
state.putCharSequence(App.VSTUP, vstup.getText());
}
@Override
public void onRestoreInstanceState(Bundle state) {
super.onRestoreInstanceState(state);
vstup.setText(state.getCharSequence(App.VSTUP));
}
Mit Fragment
s funktioniert dies nur in sehr spezifischen Situationen. Was schrecklich bricht, ist insbesondere, ein Fragment zu ersetzen, es in den hinteren Stapel zu legen und dann den Bildschirm zu drehen, während das neue Fragment angezeigt wird. Soweit ich verstanden habe, erhält das alte Fragment beim Ersetzen keinen Aufruf, onSaveInstanceState()
bleibt aber irgendwie mit dem verbunden, Activity
und diese Methode wird später aufgerufen, wenn View
sie nicht mehr existiert. Suchen Sie also nach einem meiner TextView
Ergebnisse in a NullPointerException
.
Außerdem fand ich, dass es TextViews
bei Fragment
s keine gute Idee ist , den Verweis auf my zu behalten , auch wenn es bei s in Ordnung war Activity
. In diesem Fall wird onSaveInstanceState()
der Status tatsächlich gespeichert, aber das Problem tritt erneut auf, wenn ich den Bildschirm zweimal drehe, wenn das Fragment ausgeblendet ist, da onCreateView()
es in der neuen Instanz nicht aufgerufen wird.
Ich dachte an den Staat bei der Rettung onDestroyView()
in einem gewissen Bundle
Typ Klasse Mitglied Element (es ist eigentlich mehr Daten, nicht nur ein TextView
) und Speicher dass in , onSaveInstanceState()
aber es gibt auch andere Nachteile. In erster Linie, wenn das Fragment wird zur Zeit gezeigt, die um die beiden Funktionen des Aufrufs wird umgekehrt, so dass ich zu Konto für zwei verschiedene Situationen brauchen würde. Es muss eine sauberere und korrekte Lösung geben!
quelle
Antworten:
Um den Instanzstatus von
Fragment
Ihnen korrekt zu speichern, gehen Sie wie folgt vor:1. Speichern Sie im Fragment den Instanzstatus, indem Sie ihn überschreiben
onSaveInstanceState()
und wiederherstellen inonActivityCreated()
:2. Und wichtiger Punkt in der Aktivität ist, dass Sie die Instanz des Fragments in speichern
onSaveInstanceState()
und wiederherstellen müssenonCreate()
.Hoffe das hilft.
quelle
Dies ist die Art und Weise, wie ich sie gerade benutze ... es ist sehr kompliziert, aber es behandelt zumindest alle möglichen Situationen. Falls jemand interessiert ist.
Alternativ ist es immer möglich, die Daten in passiven
View
s in VariablenView
anzuzeigen und die s nur zur Anzeige zu verwenden, um die beiden Dinge synchron zu halten. Ich halte den letzten Teil allerdings nicht für sehr sauber.quelle
A
undB
woA
sich derzeit auf dem Backstack befindet undB
sichtbar ist, verlieren Sie den ZustandA
(des Unsichtbaren) eins) wenn Sie die Anzeige zweimal drehen . Das Problem ist, dassonCreateView()
nur in diesem Szenario nicht aufgerufen wirdonCreate()
. DaheronSaveInstanceState()
gibt es später keine Ansichten, vor denen der Status gespeichert werden kann. Man müsste den übergebenen Zustand speichern und dann speichernonCreate()
.App.VSTUP
undApp.STAV
sind beide String - Tags , die repräsentieren die Objekte , die sie zu erhalten versuchen. Beispiel:savedState = savedInstanceState.getBundle(savedGamePlayString);
odersavedState.getDouble("averageTime")
In der neuesten Support-Bibliothek ist keine der hier diskutierten Lösungen mehr erforderlich. Sie können mit Ihren
Activity
Fragmenten spielen, wie Sie möchtenFragmentTransaction
. Stellen Sie einfach sicher, dass Ihre Fragmente entweder mit einer ID oder einem Tag identifiziert werden können.Die Fragmente werden automatisch wiederhergestellt, solange Sie nicht versuchen, sie bei jedem Aufruf von neu zu erstellen
onCreate()
. Stattdessen sollten Sie überprüfen, obsavedInstanceState
nicht null ist, und in diesem Fall die alten Verweise auf die erstellten Fragmente finden.Hier ist ein Beispiel:
Beachten Sie jedoch, dass derzeit ein Fehler beim Wiederherstellen des verborgenen Status eines Fragments vorliegt. Wenn Sie Fragmente in Ihrer Aktivität verstecken, müssen Sie diesen Status in diesem Fall manuell wiederherstellen.
quelle
FragmentPagerAdapter
oder geändertFragmentStatePagerAdapter
. Wenn Sie sich beispielsweise den Code von ansehenFragmentStatePagerAdapter
, werden Sie feststellen, dass dierestoreState()
Methode die Fragmente aus demFragmentManager
Parameter wiederherstellt, den Sie beim Erstellen des Adapters übergeben haben.Ich möchte nur die Lösung nennen, die ich gefunden habe und die alle in diesem Beitrag vorgestellten Fälle behandelt, die ich von Vasek und devconsole abgeleitet habe. Diese Lösung behandelt auch den Sonderfall, wenn das Telefon mehr als einmal gedreht wird, während Fragmente nicht sichtbar sind.
Hier speichere ich das Bundle für die spätere Verwendung, da onCreate und onSaveInstanceState die einzigen Aufrufe sind, die ausgeführt werden, wenn das Fragment nicht sichtbar ist
Da destroyView in der speziellen Rotationssituation nicht aufgerufen wird, können wir sicher sein, dass wir es verwenden sollten, wenn es den Status erstellt.
Dieser Teil wäre der gleiche.
Jetzt hier ist der schwierige Teil. In meiner onActivityCreated-Methode instanziiere ich die Variable "myObject", aber die Rotation erfolgt onActivity und onCreateView wird nicht aufgerufen. Daher ist myObject in dieser Situation null, wenn sich die Ausrichtung mehr als einmal dreht. Ich kann dies umgehen, indem ich dasselbe Bundle, das in onCreate gespeichert wurde, wiederverwenden kann wie das ausgehende Bundle.
Wo immer Sie den Status wiederherstellen möchten, verwenden Sie einfach das Paket "savedState"
quelle
Dank DroidT habe ich Folgendes gemacht:
Mir ist klar, dass wenn das Fragment onCreateView () nicht ausführt, seine Ansicht nicht instanziiert wird. Wenn das Fragment auf dem Backstack seine Ansichten nicht erstellt hat, speichere ich den zuletzt gespeicherten Status. Andernfalls erstelle ich mein eigenes Bundle mit den Daten, die ich speichern / wiederherstellen möchte.
1) Erweitern Sie diese Klasse:
2) In Ihrem Fragment müssen Sie Folgendes haben:
3) Sie können beispielsweise hasSavedState in onActivityCreated aufrufen:
quelle
quelle