2012-05-03 18 views
31

Mam awarię małpa którejAwaria zapisywania stanu - target nie w menedżerze fragment (setTargetFragment)

java.lang.IllegalStateException: Failure saving state: FragmentB has target not in fragment manager: FragmentA 
at android.support.v4.app.FragmentManagerImpl.saveAllState(FragmentManager.java:1561) 
at android.support.v4.app.FragmentActivity.onSaveInstanceState(FragmentActivity.java:475) 
at com.acme.ParentActivity.onSaveInstanceState(Unknown Source) 

Zasadniczo Fragmenta ładunków FragmentB i setTargetFragment nazywa ustawić docelowy fragment FragmentB użytkownika.

FragmentB po prostu wywołuje getTargetFragment w metodzie onCreate i zawiesza się na celu, gdy jest to konieczne.

Teraz nic nie robię w żadnych wywołaniach onSaveInstanceState z fragmentem docelowym pod względem ustawiania wartości NULL, wywołując dowolne wywołania saveFragmentInstanceState, putFragment itd. Pytanie brzmi, czy powinienem coś z tym zrobić?

Z góry dziękuję,

Peter.

** Edycja 1 ** ** Używam starszej wersji biblioteki pomocy technicznej i mam wrażenie, że może to być naprawione w najnowszej wersji, przetestuje dalej i zapewni dalszą aktualizację, jeśli tak jest. Wciąż jednak interesuje mnie, czy powinienem robić cokolwiek z docelowym fragmentem, którego obecnie nie robię.

** Edytuj 1 ** Naprawiono za pomocą wersji 8 biblioteki pomocy technicznej (nie próbowałem innych).

+0

Aktualizacja do R7 biblioteki wsparcia v4 wydaje się, że pracował dla mnie. – louielouie

+1

o tym samym problemie z v4r18 – njzk2

Odpowiedz

5

Wpadliśmy w tej kwestii w ostatnim czasie. Zaimplementowaliśmy niestandardową kartę rozszerzającą android.support.v4.app. FragmentStatePagerAdapter. Z android.support.v4.app. FragmentManager, przygotowaliśmy kilka fragmentów w pagerach, a także kilka innych fragmentów poza pageriem. Fragmenty są zarządzane w jednym działaniu. Istnieją przypadki, w których ustawiamy obiekt docelowy (z setTargetFragment) niepartycjonujących fragmentów na fragmenty, które mogą ale nie muszą znajdować się w adapterze stronicowania. Ponieważ FragmentStatePagerAdapter zawiera tylko pewną liczbę fragmentów, fragmenty, które zostały ustawione jako cele i które nie są już potrzebne, zostały zniszczone ... i potencjalnie niespójny stan, jeśli fragmenty, które miały te cele, nadal istniały. Doprowadziło to do zgłaszania wyjątku, gdy aplikacja straciła ostrość (zarówno po wyłączeniu ekranu, jak i po pogrążeniu aplikacji w tle), tj. Po wywołaniu onSaveInstanceState. Aby uniknąć tego wyjątku, w onSaveInstanceState, sprawdziliśmy, które fragmenty były aktualnie w menedżerze fragmentów. Jeśli wystąpiły jakiekolwiek niespójności (np. Brak fragmentu "docelowego"), usunęliśmy fragment, który miał ten cel. W naszym przypadku mieliśmy tylko trzy fragmenty, w których ustalaliśmy cel, więc wiedzieliśmy dokładnie, czego szukać.

Nie sądzę, że istnieje jakakolwiek inna metoda radzenia sobie z tą sprawą, ale jeśli ktoś ma jakąkolwiek pomocną informację, byłby bardzo ceniony.

11

Oto obejście:

umieścić to we fragmencie, który powoduje problemy:

@Override 
public void onSaveInstanceState(final Bundle outState) { 
    setTargetFragment(null, -1); 
      ... 

i pamiętać, aby ustawić go do rzeczywistego docelowego fragmentu, gdy jest to potrzebne.

+0

czy możesz wyjaśnić więcej –

+0

@MinaFawzy Co dokładnie wyjaśnić? Zostaje zresetowany, aby nie powodował więcej problemów. –

+0

Mam ten sam problem, nie wiem co dokładnie powoduje ten problem, nie używam onS SaveInstance w żadnym z moich fragmentów i nadal mam ten problem, dlatego mam nadzieję, że podasz kilka ogólnych informacji na temat tego problemu i dlaczego wybrałeś tę odpowiedź you –

4

Upewnij się, że oba fragmenty zostały dodane do backstacku!

Właśnie napotkałem ten problem podczas dodawania nowego "wywoływanego" fragmentu dla wyniku znajdującego się na szczycie fragmentu "docelowego". Początkowo otrzymywałem ten sam błąd, który przestał występować, gdy tylko dodałem oba fragmenty do tylnego stosu, gdy je użyłem.

Problem wystąpił podczas obracania ekranu, więc można go było łatwo odtworzyć.

+0

W moim przypadku jeden z fragmentów jest częścią ViewPagera, a więc nie na backstacku i nie mogę go tam dodać. Obejście problemu @androiddeveloper zadziałało w moim przypadku. W każdym razie twoje rozwiązanie brzmi jak droga :) – WarrenFaith

+0

Dzięki temu działa jak urok;) –

19

Istnieje rzeczywiście dwie rzeczy należy zrobić, aby rozwiązać ten problem:

1. Upewnij się, że używasz getChildFragmentManager() nie getFragmentManager() przy uruchamianiu FragmentB z Fragmenta

Wywołanie getChildFragmentManager() będzie zwróć hostujący fragment FragmentManager, natomiast getFragmentManager() zwróci FragmentManager Activity hostingu. Ważne jest, aby użyć getChildFragmentManager(), ponieważ zagnieżdżasz Fragment wewnątrz innego Fragmentu, więc Fragment nadrzędny powinien być odpowiedzialny za obsługę wszelkich transakcji z zagnieżdżonym Fragmentem. Jeśli użyjesz funkcji getFragmentManager(), napotkasz problem, którego doświadczasz właśnie teraz.

2. Nie używaj setTargetFragment() i getTargetFragment(), to nie będzie działać przy użyciu getChildFragmentManager()

Zamiast używać getParentFragment(). Wierzę, że jest jakiś błąd w Androidzie teraz gdzie nawet jeśli właściwie nazwać

fragmentB.setTargetFragment(fragmentA, 0);

a następnie pokazać FragmentB po zmianie konfiguracji, nazywając getTargetFragment() z FragmentB powróci sam zamiast FragmentA.

+0

Odpowiada to doskonale. To są dwa powody, dla których możesz otrzymać ten wyjątek. – tomrozb

+1

Niestety, przy korzystaniu z 'PreferenceDialogFragmentCompat' z biblioteki preferencji pomocy technicznej v7, punkt 2 nie może być zapewniony, ponieważ biblioteka wsparcia wykonuje wywołanie' getTargetFragment() ' – Madeyedexter

2

Właśnie w obliczu tego problemu i to, co myślę, że się dzieje i jak to naprawić go:

instancję Fragmenta jest zniszczony, a drugi jest tworzony, gdy jest obrót urządzenia, na przykład. Kiedy tak się dzieje, twój FragmentB zatrzymuje odnośnik do Fragmentu A, który już nie istnieje.

W takim przypadku należy zresetować cel FragmentB, aby był nową instancją FragmentA.

Zrobiłem to z następującego kodu w Fragmenta:

@Override 
    public void onAttach(Context context) { 

     super.onAttach(context); 

     FragmentB fragment = (FragmentB) getFragmentManager().findFragmentByTag(FragmentBtag); 

     if (fragment != null) { 
      fragment.setTargetFragment(this, 0); 
     } 


    } 

ten sposób, gdy Fragmenta jest dołączony do kontekstu, tzn obrót urządzenie dzieje, cel FragmentB jest wyzerowany, jeśli FragmentB powstał na z pierwszej ręki (jeśli tak, to na FragmentManager).

Mam nadzieję, że to pomaga.

+0

Awesome, to działało znacznie lepiej dla mnie. – Chaos

2

Miałem ten problem, gdy pokazano DialogFrament z innego fragmentu i przy użyciu setTargetFragment w DialogFragment. Problem został rozwiązany za pomocą metody getChildFragmentManager() podczas wyświetlania DialogFragment.

  1. ActivityA dodany Fragmenta
  2. Fragmenta dodany DialogFragmentB użyciu ActivityA za FragmentManager.
  3. nazwie dialogFragmentB.setTargetFragment (Fragmenta)
  4. Fragmenta usunięto i dodano nową instancję Fragmenta
  5. FragmentManager związane z ActivityA nadal zawierał DialogFragmentB który miał pierwszy przykład Fragmenta jako fragment docelowego.

To spowodowało wywołanie wyjątku "Zapis stanu - cel nie w zarządzaniu fragmentami".

0

W moim przypadku problem polegał na wywołaniu setTargetFragment na niewłaściwym fragmencie.

Czy: FragmentA.setTargetFragment(FragmentB);

Powinno być: FragmentB.setTargetFragment(FragmentA);

Powiązane problemy