10

Mam dość duży problem i nie do końca rozumiem, co się dzieje. Zajmuję się tworzeniem aplikacji korzystającej z Fragmentów (z biblioteki wsparcia) i używam FragmentTransaction.replace() do umieszczania nowych Fragmentów na stosie wstecznym i zastępowania starego. Kod wygląda następująco:Fragment systemu Android Zobacz Utratę stanu przy użyciu FragmentTransaction.replace()

FragmentManager fm = getSupportFragmentManager(); 
FragmentTransaction ft = ft.beginTransaction(); 
// Animations in my res/anim folder 
ft.setCustomAnimations(R.anim.slide_in_right, R.anim.slide_out_left, R.anim.slide_in_left, R.anim.slide_out_right); 
ft.replace(R.id.fragment_container, newFragment, tag); 
ft.addToBackStack(null); 
ft.commit(); 

Pomoże to w zastąpieniu mojego fragmentu. Mój problem jest następujący. W jednym fragmencie mam listę elementów zbudowanych na podstawie danych wprowadzanych przez użytkownika. Teraz, gdy użytkownik kliknie następny, a następnie kliknie przycisk Wstecz (aby powrócić do listy), lista jest pusta, ponieważ widok jest niszczony. Teraz, zauważyłem następujące:

  1. onSaveInstanceState nie jest wywoływana. Sądzę, że dzieje się tak dlatego, że jest to wywoływane tylko wtedy, gdy aktywna jest akcja rodzica. Na podstawie dokumentów: "Istnieje wiele sytuacji, w których fragment może być w większości zburzony (np. Po umieszczeniu go na tylnym stosie bez wyświetlania interfejsu użytkownika), ale jego stan nie zostanie zapisany, dopóki jego własna aktywność rzeczywiście nie uratuje jego stanu . ". Wygląda na to, że zastąpienie FragmentTransaction nie jest jednym z tych czasów. Czy ktoś ma potwierdzenie tego lub lepszego wyjaśnienia?
  2. setOnRetainInstanceState (true) nie jest pomocne w tej sytuacji. Ponownie, uważam, że ma to związek z informacjami z dokumentów: "Kontroluj, czy instancja fragmentu jest zachowywana podczas ponownego tworzenia aktywności (na przykład ze zmiany konfiguracji)". Nie wykonuję żadnych czynności podczas ponownego tworzenia działania, więc to nie ma sensu.

Zgaduję, że moje główne pytanie brzmi: czy istnieje sposób na zachowanie stanu widoku (po prostu zatrzymanie fragmentu) podczas korzystania z replace? Jest FragmentTransaction.add(), ale jest też kilka problemów z tym. Jedną z nich jest to, że animacja wyjścia nie jest wykonywana, dlatego animacja nie jest poprawna. Innym jest, że nowy Fragment, który stary fragment (ten, który jest wprowadzany w stanie niewidocznym) jest wciąż klikalny. Na przykład, jeśli mam obiekt ListFragment i umieszczam na nim fragment zawartości za pomocą polecenia dodawania, nadal można kliknąć elementy listy w obiekcie ListFragment.

Odpowiedz

2

Bez możliwości zobaczenia kodu fragmentów, to jest trochę odgadnąć, ale w przeszłości natknąłem się na ten sam problem i stwierdziłem, że resetowanie adaptera w twoim ListFragment w onViewStateRestored wydaje się Zrób sztuczkę.

public void onViewStateRestored (Bundle savedInstanceState) 
{ 
    super.onViewStateRestored (savedInstanceState); 
    setListAdapter(new ArrayAdapter(Activity, R.layout.nav_item, objects)); 
} 

Co jest dziwne, biorąc pod uwagę dokumentację twierdzi, że ta metoda jest wywoływana po onActivityCreated ale przed onStart. Wydaje się jednak, że jest on również wywoływany w innym czasie, ponieważ kiedy ostatnia transakcja fragmentu jest wyrzucana z tyłu stosu, ta metoda jest wywoływana przed wyświetleniem poprzednio zamienionego fragmentu. Aktywność, która jest właścicielem fragmentów, nie została w żaden sposób zatrzymana ani zasłonięta, więc zgodnie z dokumentami onViewStateRestored nie należy wywoływać, ponieważ tylko fragmenty zostały zmodyfikowane. Ale i tak to i tak działa.

2

Wygląda na to, że wystarczy upewnić się, że poprawnie zaimplementowano wCreateView i onDestroyView. Sytuacja, którą opisujesz, zdaje się wskazywać, że gdy fragment listy zostanie umieszczony na tylnym stosie (w wyniku wymiany transakcji), Android wywołujeDestroyView, aby zwolnić niektóre zasoby. Jednak najwyraźniej nie zniszczył fragmentu listy, ponieważ po stuknięciu cofasz to samo wystąpienie fragmentu.

Zakładając, że to wszystko jest prawdziwe, wtedy, gdy użytkownik kliknie z powrotem system Android, wywoła onCreateView. Każdy stan, który zapisałeś w zmiennych instancji fragmentu, powinien nadal tam być i wszystko, co musisz zrobić, to ponownie zaludnić widok ...może ustawić adapter na ListView lub cokolwiek innego.

Upewnij się również, że wywołanie zwrotne onSaveInstanceState() faktycznie zapisuje stan każdej instancji, która jest konieczna do odbudowania widoku. W ten sposób, jeśli fragment faktycznie zostanie całkowicie zniszczony, FragmentManager może przywrócić stan, kiedy będzie musiał później odjąć fragment.

Powiązane problemy