Znalazłem wiele przykładów podobnych pytań dotyczących SO, ale żadna odpowiedź niestety nie spełnia moich wymagań.
Mam różne układy dla portretu i krajobrazu i używam tylnego stosu, co zarówno uniemożliwia mi używanie, jak setRetainState()
i sztuczki przy użyciu procedur zmiany konfiguracji.
Wyświetlam pewne informacje użytkownikowi w TextViews, które nie są zapisywane w domyślnym module obsługi. Podczas pisania mojej aplikacji wyłącznie przy użyciu działań następujące działały dobrze:
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));
}
W przypadku Fragment
s działa to tylko w bardzo specyficznych sytuacjach. W szczególności, co strasznie się psuje, to zastępowanie fragmentu, umieszczanie go na tylnym stosie, a następnie obracanie ekranu podczas wyświetlania nowego fragmentu. Z tego, co zrozumiałem, stary fragment nie otrzymuje wywołania, onSaveInstanceState()
gdy jest zastępowany, ale pozostaje w jakiś sposób powiązany z, Activity
a ta metoda jest wywoływana później, gdy View
już nie istnieje, więc szukam dowolnego z moich TextView
wyników w NullPointerException
.
Odkryłem również, że zachowanie odniesienia do mojego TextViews
nie jest dobrym pomysłem w przypadku Fragment
s, nawet jeśli było w porządku z Activity
s. W takim przypadku onSaveInstanceState()
faktycznie zapisuje stan, ale problem pojawia się ponownie, jeśli obrócę ekran dwukrotnie, gdy fragment jest ukryty, ponieważ onCreateView()
nie zostanie wywołany w nowej instancji.
Myślałam o zapisaniu stanu w onDestroyView()
do pewnego Bundle
typu a elementem członkiem klasy (to faktycznie więcej danych, a nie tylko jeden TextView
) i zapisując to w onSaveInstanceState()
ale istnieją inne wady. Przede wszystkim, jeśli fragment jest obecnie wyświetlany, kolejność wywoływania dwóch funkcji jest odwrócona, więc musiałbym wziąć pod uwagę dwie różne sytuacje. Musi być czystsze i prawidłowe rozwiązanie!
źródło
Odpowiedzi:
Aby poprawnie zapisać stan instancji
Fragment
, wykonaj następujące czynności:1. We fragmencie zapisz stan instancji, zastępując
onSaveInstanceState()
i przywracając wonActivityCreated()
:2. I ważne jest , aby w ćwiczeniu zapisać instancję fragmentu
onSaveInstanceState()
i przywrócićonCreate()
.Mam nadzieję że to pomoże.
źródło
Tego właśnie używam w tej chwili ... jest to bardzo skomplikowane, ale przynajmniej obsługuje wszystkie możliwe sytuacje. W razie zainteresowania.
Alternatywnie , zawsze jest możliwość utrzymania danych wyświetlanych w pasywnych
View
sw zmiennych i używaniaView
s tylko do ich wyświetlania, utrzymując synchronizację dwóch elementów. Jednak nie uważam ostatniej części za bardzo czystą.źródło
A
aB
gdzieA
znajduje się on obecnie w plecaku iB
jest widoczny, tracisz stanA
(niewidzialnego) jeden), jeśli obrócisz wyświetlacz dwukrotnie . Problem polega na tym, żeonCreateView()
nie jest wywoływany tylko w tym scenariuszuonCreate()
. Więc późniejonSaveInstanceState()
nie ma żadnych widoków, z których można by zapisać stan. Trzeba będzie zapisać, a następnie zapisać przekazany stanonCreate()
.App.VSTUP
iApp.STAV
to zarówno tagi ciąg, który reprezentuje obiekty starają się uzyskać. Przykład:savedState = savedInstanceState.getBundle(savedGamePlayString);
lubsavedState.getDouble("averageTime")
W najnowszej bibliotece wsparcia żadne z omawianych tutaj rozwiązań nie jest już konieczne. Możesz bawić się swoimi
Activity
fragmentami tak, jak lubisz, używającFragmentTransaction
. Upewnij się tylko, że twoje fragmenty można zidentyfikować za pomocą identyfikatora lub tagu.Fragmenty zostaną przywrócone automatycznie, o ile nie spróbujesz ich odtworzyć przy każdym wywołaniu
onCreate()
. Zamiast tego powinieneś sprawdzić, czysavedInstanceState
nie ma wartości null, i w tym przypadku znaleźć stare odniesienia do utworzonych fragmentów.Oto przykład:
Zauważ jednak, że obecnie występuje błąd podczas przywracania ukrytego stanu fragmentu. Jeśli ukrywasz fragmenty w swojej działalności, w takim przypadku musisz ręcznie przywrócić ten stan.
źródło
FragmentPagerAdapter
lubFragmentStatePagerAdapter
. Jeśli spojrzysz na przykład na kodFragmentStatePagerAdapter
, zobaczysz, żerestoreState()
metoda przywraca fragmenty zFragmentManager
przekazanego jako parametr podczas tworzenia adaptera.Chcę tylko podać rozwiązanie, które wymyśliłem, które obsługuje wszystkie przypadki przedstawione w tym poście, które wyprowadziłem z Vasek i devconsole. To rozwiązanie obsługuje również specjalny przypadek, gdy telefon jest obracany więcej niż raz, a fragmenty nie są widoczne.
Oto, gdzie przechowuję pakiet do późniejszego wykorzystania, ponieważ onCreate i onSaveInstanceState to jedyne wywołania, które są wykonywane, gdy fragment nie jest widoczny
Ponieważ destroyView nie jest wywoływany w sytuacji specjalnej rotacji, możemy być pewni, że jeśli stworzy on stan, powinniśmy go użyć.
Ta część byłaby taka sama.
Teraz tutaj jest skomplikowana część. W mojej metodzie onActivityCreated tworzę instancję zmiennej „myObject”, ale obrót odbywa się na onActivity, a onCreateView nie zostaje wywołany. Dlatego myObject będzie zerowy w tej sytuacji, gdy orientacja zostanie obrócona więcej niż jeden raz. Obejście tego problemu polega na ponownym użyciu tego samego pakietu, który został zapisany w programie onCreate jako pakietu wychodzącego.
Teraz gdziekolwiek chcesz przywrócić stan, po prostu użyj pakietu saveState
źródło
Dzięki DroidT zrobiłem to:
Zdaję sobie sprawę, że jeśli Fragment nie wykona funkcji onCreateView (), jego widok nie zostanie utworzony. Jeśli więc fragment na tylnym stosie nie utworzył swoich widoków, zapisuję ostatni zapisany stan, w przeciwnym razie buduję własny pakiet z danymi, które chcę zapisać / przywrócić.
1) Rozszerz tę klasę:
2) W swoim fragmencie musisz mieć to:
3) Na przykład możesz wywołać hasSavedState w onActivityCreated:
źródło
źródło