Na stan fragmentu mogą wpływać różne operacje systemu Android. Aby zapewnić zapisanie stanu użytkownika, platforma Androida automatycznie zapisuje i przywraca fragmenty i stos wsteczny. Dlatego musisz dopilnować, aby wszelkie dane z tego fragmentu również zostały zapisane i przywrócone.
W tabeli poniżej zebraliśmy operacje, które powodują utratę stanu fragmentu, a także informacje o tym, czy różne typy stanu utrzymują się po tych zmianach. W tabeli wymienione są następujące typy stanów:
- Zmienne: zmienne lokalne we fragmencie.
- Stan widoku: wszelkie dane, które należą do co najmniej jednego widoku danych we fragmencie.
- SavedState: dane powiązane z tą instancją fragmentu, które powinny zostać zapisane w elemencie
onSaveInstanceState()
. - NonConfig: dane pobrane ze źródła zewnętrznego, takie jak serwer lub lokalne repozytorium, albo dane utworzone przez użytkowników, które są wysyłane na serwer po zatwierdzeniu.
Często Zmienne są traktowane tak samo jak SavedState, ale w poniższej tabeli rozróżniono je, aby pokazać wpływ różnych operacji na każdą z nich.
Operacja | Zmienne | Stan widoku danych | SavedState | Brak konfiguracji |
---|---|---|---|---|
Dodano do stosu wstecznego | ✓ | ✓ | x | ✓ |
Zmiana konfiguracji | x | ✓ | ✓ | ✓ |
Proces śmierci/rekreacji | x | ✓ | ✓ | ✓* |
Usunięto, nie dodano do stosu wstecznego | x | x | x | x |
Host zakończony | x | x | x | x |
* Stan braku konfiguracji można zachować po zakończeniu zakończenia procesu za pomocą modułu Zapisanego stanu dla ViewModel.
Tabela 1. Różne operacje niszczenia fragmentów i ich wpływ na różne typy stanu.
Przeanalizujmy konkretny przykład. Rozważmy ekran, który generuje losowy ciąg znaków, wyświetla go w elemencie TextView
i udostępnia opcję edytowania ciągu przed wysłaniem go do znajomego:
W tym przykładzie załóżmy, że gdy użytkownik kliknie przycisk edycji, aplikacja wyświetli widok EditText
, w którym użytkownik może edytować wiadomość. Jeśli użytkownik kliknie ANULUJ, widok EditText
powinien zostać wyczyszczony, a jego widoczność jest ustawiona na View.GONE
. Taki ekran może wymagać zarządzania 4 elementami danych, aby zapewnić bezproblemową obsługę:
Dane | Typ | Typ stanu | Opis |
---|---|---|---|
seed |
Long |
Brak konfiguracji | Nasiona używane do losowego generowania nowego dobrego ustanowienia. Generujony podczas tworzenia ViewModel . |
randomGoodDeed |
String |
SavedState + zmienna | Generujony podczas tworzenia fragmentu po raz pierwszy.
Zapis randomGoodDeed jest zapisywany, aby użytkownicy widzieli ten sam losowy dobra czynność nawet po śmierci i regeneracji. |
isEditing |
Boolean |
SavedState + zmienna | Gdy użytkownik rozpoczyna edytowanie, flaga wartości logicznej jest ustawiona na true .
Element isEditing jest zapisywany, aby edytowalna część ekranu była widoczna po odtworzeniu fragmentu. |
Edytowany tekst | Editable |
Wyświetl stan (będący własnością firmy EditText ) |
Edytowany tekst w widoku EditText .
Widok EditText zapisuje ten tekst, aby zapewnić, że zmiany wprowadzane przez użytkownika nie zostaną utracone. |
Tabela 2. Wskazuje, że aplikacja do generowania losowych tekstów musi zarządzać aplikacją.
W poniższych sekcjach opisano, jak prawidłowo zarządzać stanem danych za pomocą operacji destrukcyjnych.
Wyświetl stan
Za zarządzanie własnym stanem odpowiadają widoki danych. Jeśli np. widok przyjmuje dane wejściowe użytkownika, jego obowiązkiem jest zapisanie i przywrócenie tych danych w celu obsługi zmian w konfiguracji. Wszystkie widoki udostępniane przez platformę Androida mają własną implementację znaczników onSaveInstanceState()
i onRestoreInstanceState()
, więc nie musisz zarządzać stanem widoku w obrębie tego fragmentu.
Na przykład w poprzednim scenariuszu edytowany ciąg znaków jest utrzymywany w elemencie EditText
. Element EditText
zna wartość wyświetlanego tekstu oraz inne szczegóły, takie jak początek i koniec dowolnego zaznaczonego tekstu.
Widok wymaga identyfikatora, aby zachować stan. Ten identyfikator musi być unikalny w obrębie fragmentu i jego hierarchii widoków. Widoki bez identyfikatora nie zachowują swojego stanu.
<EditText android:id="@+id/good_deed_edit_text" android:layout_width="match_parent" android:layout_height="wrap_content" />
Jak wspomniano w tabeli 1, widoki zapisują i przywracają ViewState
we wszystkich operacjach, które nie usuwają fragmentu ani nie niszczą hosta.
SavedState
Twój fragment odpowiada za zarządzanie niewielkimi ilościami stanu dynamicznego, które są integralną częścią jego działania. Dane zserializowane możesz przechowywać w prosty sposób za pomocą narzędzia Fragment.onSaveInstanceState(Bundle)
.
Podobnie jak w przypadku Activity.onSaveInstanceState(Bundle)
, dane umieszczone w pakiecie są zachowywane przez zmiany konfiguracji, proces śmierci i regeneracji oraz są dostępne w metodach onCreate(Bundle)
, onCreateView(LayoutInflater, ViewGroup, Bundle)
i onViewCreated(View, Bundle)
danego fragmentu.
Kontynuując poprzedni przykład, randomGoodDeed
to akt wyświetlany użytkownikowi, a isEditing
to flaga określająca, czy fragment pokazuje, czy ukrywa EditText
. Ten zapisany stan powinien się utrzymywać za pomocą parametru onSaveInstanceState(Bundle)
, jak w tym przykładzie:
Kotlin
override fun onSaveInstanceState(outState: Bundle) { super.onSaveInstanceState(outState) outState.putBoolean(IS_EDITING_KEY, isEditing) outState.putString(RANDOM_GOOD_DEED_KEY, randomGoodDeed) }
Java
@Override public void onSaveInstanceState(@NonNull Bundle outState) { super.onSaveInstanceState(outState); outState.putBoolean(IS_EDITING_KEY, isEditing); outState.putString(RANDOM_GOOD_DEED_KEY, randomGoodDeed); }
Aby przywrócić stan w onCreate(Bundle)
, pobierz zapisaną wartość z pakietu:
Kotlin
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) isEditing = savedInstanceState?.getBoolean(IS_EDITING_KEY, false) randomGoodDeed = savedInstanceState?.getString(RANDOM_GOOD_DEED_KEY) ?: viewModel.generateRandomGoodDeed() }
Java
@Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (savedInstanceState != null) { isEditing = savedInstanceState.getBoolean(IS_EDITING_KEY, false); randomGoodDeed = savedInstanceState.getString(RANDOM_GOOD_DEED_KEY); } else { randomGoodDeed = viewModel.generateRandomGoodDeed(); } }
Jak wspomnieliśmy w tabeli 1, zmienne są zachowywane, gdy fragment zostanie umieszczony na stosie wstecznym. Zapisujemy je w stanie, aby zachować trwałość we wszystkich niszczycielskich operacjach.
Brak konfiguracji
Dane nonConfig należy umieszczać poza własnym fragmentem, np. w ViewModel
. W poprzednim przykładzie powyżej seed
(nasz stan braku konfiguracji) jest generowany w ViewModel
.
Logika utrzymywania stanu należy do platformy ViewModel
.
Kotlin
public class RandomGoodDeedViewModel : ViewModel() { private val seed = ... // Generate the seed private fun generateRandomGoodDeed(): String { val goodDeed = ... // Generate a random good deed using the seed return goodDeed } }
Java
public class RandomGoodDeedViewModel extends ViewModel { private Long seed = ... // Generate the seed private String generateRandomGoodDeed() { String goodDeed = ... // Generate a random good deed using the seed return goodDeed; } }
Klasa ViewModel
z założenia pozwala danemu przetrwać zmiany konfiguracji, takie jak obrót ekranu, i pozostaje w pamięci, gdy fragment zostanie umieszczony w stosie wstecznym. Po zakończeniu procesu śmierci i reprodukcji klucz ViewModel
jest odtworzony i generowany jest nowy seed
. DodanieSavedState
modułu do ViewModel
umożliwia ViewModel
zachowanie prostego stanu przez
śmierć i odtwarzanie procesu.
Dodatkowe materiały
Więcej informacji o zarządzaniu stanem fragmentu znajdziesz w dodatkowych materiałach poniżej.
Ćwiczenia z programowania
- Ćwiczenie z programowania dotyczące komponentów dopasowanych do cyklu życia