Die automatische Änderung der UI-Konfigurationsänderung in Aktivität und Fragment schlägt manchmal fehl

8

Ich habe schon lange Android-App geschrieben, aber jetzt habe ich ein Problem, über das ich nie nachgedacht habe. Es handelt sich um den Android-Lebenszyklus von Activitys und Fragments in Bezug auf Konfigurationsänderungen. Dafür habe ich eine kleine Anwendung mit diesem notwendigen Code erstellt:

%Vor%

Und hier ist mein Code für die TestFragment . Beachten Sie, dass ich setRetainInstance(true); in der onCreate -Methode anrufe, damit das Fragment nach einer Konfigurationsänderung nicht erneut eingegeben wird.

%Vor%

Und hier ist das Layout, das mein Fragment verwendet:

%Vor%

Mein Problem ist, dass wenn ich das Gerät rotiere, der Text von Button wieder auf den Standardwert zurückgesetzt wird. Natürlich ist die View der Fragment neu erstellt und aufgebläht, aber die gespeicherte Instanz für die Views sollte wiederhergestellt werden. Ich habe auch ein EditText in meinem Layout und dort bleiben der Text und andere Eigenschaften nach der Rotation. Warum wird der Button nicht standardmäßig von Bundle wiederhergestellt? Ich habe auf der Entwicklerseite nachgelesen:

  

Standardmäßig verwendet das System den Status der Bundle-Instanz, um Informationen zu jedem View-Objekt in Ihrem Aktivitätslayout zu speichern (z. B. den in ein EditText-Objekt eingegebenen Textwert). Wenn also Ihre Aktivitätsinstanz zerstört und neu erstellt wird, wird der Status des Layouts in den vorherigen Zustand zurückversetzt, ohne dass Sie Code benötigen.

Ich habe in den letzten Tagen auch viele Antworten gelesen, aber ich weiß nicht, wie aktuell sie sind. Bitte hinterlasse keinen Kommentar oder eine Antwort mit android:configChanges=... das ist sehr schlecht . Ich hoffe, jemand kann Licht in meinen Mangel an Verständnis bringen.

    
Cilenco 13.08.2015, 17:10
quelle

5 Antworten

5

Sie sollten den Status Ihres Fragments in onSaveInstanceState(Bundle outState) speichern und in der Methode onViewCreated(View view, Bundle savedState) wiederherstellen. Auf diese Weise erhalten Sie die Benutzeroberfläche genauso wie vor der Konfigurationsänderung.

    
MatBos 13.08.2015 17:16
quelle
4

TextView Unterklassen speichern ihren Text nicht standardmäßig. Sie müssen freezesText="true" im Layout oder setFreezesText(true) zur Laufzeit aktivieren, damit der Status gespeichert wird.

    
kcoppock 18.08.2015 01:31
quelle
4

Gemäß der Dokumentation sollten Ansichten ihren Status beibehalten, ohne setRetainInstance(true) zu verwenden. Versuchen Sie, es aus Ihrem onCreate zu entfernen. Dadurch sollte das Fragment bei der Bildschirmdrehung neu erstellt werden. Daher sollten alle Ansichten vor der Drehung gespeichert und danach wiederhergestellt werden.

    
Ivan V 23.08.2015 07:53
quelle
4

Dieser Stapelüberlauf sollte Ihre Frage beantworten: setRetainInstance behält die Instanz nicht bei

setRetainInstance weist das Fragment an, alle seine Daten zu speichern, und für ui-Elemente, in denen der Benutzer den Status manipuliert hat (EditText, ScrollView, ListView usw.), wird der Status wiederhergestellt. Das heißt, normale schreibgeschützte UI-Komponenten werden in onCreateView von Grund auf neu gebündelt und müssen neu gesetzt werden - ich vermute, dass ihre Eigenschaften nicht als "Daten" betrachtet werden, die beibehalten und wiederhergestellt werden müssen - Google tut dies wahrscheinlich aus Leistungsgründen. Für Dinge wie einen normalen Button, ImageView oder TextView muss der Inhalt manuell festgelegt werden, wenn sie erneut aktualisiert werden, wenn sie vom ursprünglichen Status im XML-Code abweichen. (TextViews android:freezesText setzt die TextView im Grunde in einen Modus, der eine Implementierung verwendet, um ihren Status zu speichern und wiederherzustellen).

PS: Laut diesem Stapelüberlauf speichern und Wiederherstellen eines ButtonText, wenn die Bildschirmausrichtung umgeschaltet wird , Sie können android:freezesText auf der Schaltfläche setzen, damit der Text beibehalten wird - ich habe es nicht versucht, aber es macht Sinn.

    
jt-gilkeson 23.08.2015 08:50
quelle
2

Nach der Op-Rückmeldung bearbeiten

Obwohl dies die Frage nicht beantwortet, habe ich mich nach Rücksprache mit dem OP entschieden, es hier als Referenzpunkt für Informationen über das Thema für die Menschen zu belassen, die hier landen. Ich hoffe, Sie finden es hilfreich.

Versuchen Sie, Ihre setRetainInstance in onCreateView zu setzen. Siehe hier

%Vor%
  

Wird aufgerufen, wenn die Aktivität des Fragments erstellt wurde   Ansichtshierarchie des Fragments instanziiert. Es kann verwendet werden, um das Finale zu machen   Initialisierung, sobald diese Teile vorhanden sind, z. B. beim Abrufen   Ansichten oder Wiederherstellungsstatus. Es ist auch nützlich für Fragmente, die verwenden   setRetainInstance (boolean), um ihre Instanz beizubehalten, wie dies   Callback teilt dem Fragment mit, wenn es vollständig mit dem neuen verknüpft ist   Aktivitätsinstanz. Dies wird nach onCreateView (LayoutInflater,   ViewGroup, Bundle) und vor onViewStateRestored (Bundle).

developer.android.com/reference/android/app/ Fragment.html # onActivityCreated

  

Legen Sie fest, ob eine Fragmentinstanz in Activity beibehalten wird   Neuerstellung (z. B. von einer Konfigurationsänderung). Das kann nur sein   verwendet mit Fragmenten nicht im Backstack. Wenn gesetzt, das Fragment   Der Lebenszyklus unterscheidet sich geringfügig, wenn eine Aktivität neu erstellt wird:

     

onDestroy () wird nicht aufgerufen (aber onDetach () wird immer noch, weil   das Fragment wird von seiner aktuellen Aktivität gelöst.)   onCreate (Bundle) wird nicht aufgerufen, da das Fragment nicht vorhanden ist   neu erstellt.
  onAttach (Aktivität) und onActivityCreated (Bundle) werden   immer noch angerufen werden.

developer.android.com/reference/android/app/Fragment.html #setRetainInstance

Und von hier übernommen:

  

onCreate: Es wird bei der ersten Erstellung des Fragments aufgerufen. Sie machen   Ihre nicht grafischen Initialisierungen hier. Es endet noch vor dem   Layout ist aufgebläht und das Fragment ist sichtbar.

     

onCreateView: Es wird aufgerufen, das Layout des Fragments aufzublasen, d   hier erfolgt in der Regel eine grafische Initialisierung. Es heißt immer   manchmal nach der onCreate-Methode.

     

onActivityCreated: Wenn Ihre Ansicht statisch ist, verschieben Sie einen beliebigen Code nach   Die onActivityCreated-Methode ist nicht erforderlich. Aber wenn du - für   B. füllen Sie einige Listen aus dem Adapter, dann sollten Sie es tun   die onActivityCreated-Methode sowie das Wiederherstellen des Ansichtszustands wann   setRetainInstance verwendet dies. Zugriff auf die Ansichtshierarchie von   Die übergeordnete Aktivität muss in der onActivityCreated ausgeführt werden, nicht früher.

Lass es mich wissen, wenn das hilft.

    
Yvette Colomb 18.08.2015 00:16
quelle