2012-08-01 15 views
31

Chcę zrozumieć ten wyjątek w celu wprowadzenia poprawnej poprawki.java.lang.IllegalStateException: Fragment już nie istnieje dla klucza f1: index 3

Przegląd:

Jest ViewPager i używa FragmentStatePagerAdapter instancję 2 fragmenty poprzez GetItem i MyFragmentClass.newInstance(...).

adaptera GetItem wygląda następująco:

@Override 
public Fragment getItem(int position) { 
    Fragment fragment = null; 

    switch(position) { 
     case 0: 
      fragment = MyFragment2.newInstance(par1); 
      break; 
     case 1: 
      fragment = MyFragment2.newInstance(par2, par3); 
      break; 
    } 
    return fragment; 
} 

Problem:

Kiedy działalność jest zniszczony i stworzył kolejny adapter jest ponownie intantiated fragmenty stworzone dzięki MyFragmentClass.newInstance(...) ... ale potem na tej linii:

pager.setAdapter(adapter);

uzyskać wspomniany wyjątek.

Spojrzałem w źródle, gdzie jest wyjątek, to w ten sposób:

@Override 
public Fragment getFragment(Bundle bundle, String key) { 
    int index = bundle.getInt(key, -1); 
    if (index == -1) { 
     return null; 
    } 
    if (index >= mActive.size()) { 
     throw new IllegalStateException("Fragement no longer exists for key " 
       + key + ": index " + index); 
    } 
    Fragment f = mActive.get(index); 
    if (f == null) { 
     throw new IllegalStateException("Fragement no longer exists for key " 
       + key + ": index " + index); 
    } 
    return f; 
} 

więc wiązka przechodzi tam z jakiegoś stanu, który odwołuje się moje stare fragmenty, ale to nie odpowiadają obecny stan (mActive), a wyjątek zostanie zgłoszony.

Nie rozumiem, co kryje się za tym pomysłem, ani w jaki sposób mam tworzyć fragmenty ... więc nie mam pojęcia, jak rozwiązać problem.

Próbowałem też pewną sztuczkę dostałem od innego kontekstu:

pager.setOffscreenPageLimit(1);

W celu uniknięcia że fragmenty są zniszczone, gdy są poza ekranem (w przypadku 2 stron viewpager, choć don nie wiem, czy działa dobrze z adapterem stanu). Ale nie wydaje się być związane, przynajmniej, to nie pomaga, nadal uzyskać ten sam wyjątek.

To, co zrobiłem teraz, to spróbuj bloku catch wokół linii, no i dostaję puste strony zamiast crash boxa, również nie jest dobre.

+0

czy znalazłeś działające rozwiązanie dla twojego problemu? – savepopulation

+0

Czy kiedykolwiek znalazłeś rozwiązanie? –

+0

Nie pamiętam, przepraszam :( – Ixx

Odpowiedz

18

Jeśli nie chcesz, aby fragmenty były odzyskiwane, gdy są poza ekranem, powinieneś używać FragmentPagerAdapter, a nie FragmentStatePagerAdapter.

+0

jaka jest różnica w tej sytuacji? –

+2

'FragmentPagerAdapter' ładuje każdy fragment w pamięci podczas odwiedzania.' FragmentStatePagerAdapter' uwalnia swoje odniesienie do fragmentów, gdy minie parametr 'offscreenPageLimit'. – tad

+0

, więc jeśli ustawimy offscreenpagelimit to już nie problem? (dla 'FragmentStatePagerAdapter') –

33

To może pomóc -

@Override 
public Parcelable saveState() { 
    return null; 
} 

Dodaj linię powyżej w FragmentStatePagerAdapter.

+1

Dzięki attels działa jak urok – CodingRat

+2

Działa to idealnie do obsługi adaptera przywoławczego w tylnym stosie. Dzięki! –

+1

To jest praca dla mnie! – GeekHades

3

Mam problem z tym problemem przez cały dzień, ale teraz znalazłem rozwiązanie.

private ViewPager _mViewPager; 
_mViewPager.setOffscreenPageLimit(5); 
//5 is how much page you have. 

setOffscreenPageLimit Ustaw liczbę stron, które powinny zostać zachowane po obu stronach bieżącej strony w hierarchii widoku w stanie bezczynności. Strony przekraczające ten limit zostaną odtworzone z adaptera w razie potrzeby.

+0

to wykorzystuje mnóstwo pamięci ... oszczędza kłopotów związanych z nie zapisywaniem stanu i wszystkich ... ale to jest złe na dłuższą metę, gdy jest mnóstwo danych – Kushan

1

bardzo dobrze!Ponieważ jest powtórzenie pager.setAdapter(adapter); gdy wezwanie restoreState przyczyna wyjątek:

Fragment no longer exists for key f0: index 0 

możemy zwolnić Fragment RootView

public void onDestroyView() { 
    super.onDestroyView(); 
    if (isRecyclerRootViewAlways()) { 
     mRootView = null;//<-- 
    } 
    mMyFragmentLifecycle.onFragmentDestroyView(this); 
} 
0

Zastosowanie

getFragmentManager()

adapter fragmentu nie dziecko fragment manager

PagerAdapter adapter = new PagerAdapter(getFragmentManager()); 

Mam nadzieję, że to pomaga.

Powiązane problemy