2012-12-17 17 views
10

Mam mały problem: mam ViewPager z niektórymi stronami i używam FragmentStatePagerAdapter do obsługi danych. W portrecie mam na przykład 20 stron dla ViewPagera, a w krajobrazie mam tylko 10 stron dla ViewPagera. Tak więc przy zmianie orientacji tworzę nowy Adapter z różnymi Danymi.ViewPager + FragmentStatePagerAdapter + zmiana orientacji

Oto małe wyjaśnienie, dlaczego: Pokazuję jedno zdjęcie w pionie i dwa w krajobrazie, ale zawsze wszystkie w liczbie. Jeśli mam 10 zdjęć do pokazania, mam 10 w portretach i 5 w krajobrazie (zawsze dwa).

Ale teraz mam dziwny błąd: Kiedy jestem w Pejzażu na indeksie 5 i obracam urządzeniem, aktualna strona ViewPagera jest ustawiona na 10. Jeśli ponownie go włączyłem, to jestem na stronie 5. Jeśli przesunę Teraz ViewPage na stronę 10 metode getItem adaptera nigdy nie jest wywoływana, a ViewPage pokazuje mi zdjęcie jednopoziomowe, a nie dwa dla krajobrazu. Jak to się dzieje? Czy istnieje pamięć podręczna w adapterze lub w ViewPager? W onCreate of the Activity wszystko jest nowe, adapter, a także dane (tylko ciągi ze ścieżką) dla ViewPagera. Więc jakikolwiek pomysł naprawienia tej naprawdę przerażającej "funkcji"?

Oto niektóre kodu:

onCreate:

mViewPagerAdapter = new ReaderPageViewAdapter(getSupportFragmentManager(), getBaseContext(), mCurrentDocument.mPages, getResources() 
       .getConfiguration().orientation); 
    mPageReader = (ReaderViewPager) findViewById(R.id.pager); 
    mPageReader.setAdapter(mViewPagerAdapter); 

adapter GetItem:

public Fragment getItem(final int index) { 
     final PageInfo pageInfo = mPages.get(index); 
     final PageFragment pageFragment = (PageFragment) PageFragment 
       .instantiate(mContext, pageInfo.mClss.getName(), pageInfo.mArgs); 
     return pageFragment; 
    } 

Jeśli potrzebujesz czegoś więcej po prostu powiedz. Thanks

+0

Dla mnie ten http://stackoverflow.com/questions/17629463/fragmentpageradapter-how-to-handle-orientation-changes approach pasuje idealnie! – r4m

Odpowiedz

41

Można zastąpić FragmentActivity onSaveInstanceState() i nie wywołać super.onSaveInstanceState() w metodzie .

@Override 
protected void onSaveInstanceState(final Bundle outState) { 
    // super.onSaveInstanceState(outState); 
} 

Nie używajmViewPager.setSaveEnabled(false);

skończyło się z dużym memoryLeak. Po każdej zmianie orientacji umieszcza Fragmenty w tablicy FragmentManager i nigdy go nie czyści. Tak więc wzrasta zużycie pamięci do ponad 100 MB po zmianie orientacji wiele razy. Używanie metody onSaveInstanceState jest lepszym rozwiązaniem, niż myślę.

+0

Muszę sprawdzić, czy setSaveEnabled spowodowało 6 godzin debugowania przecieku pamięci. –

+0

Przepraszam, że pytam tak późno, ale czy kiedykolwiek odkryłeś, co spowodowało niespodziewane zachowanie w super.onSaveInstanceState (outState)? Z góry dziękuję ! ;-) – 2Dee

+0

Tak, jest późno :-) w onSaveInstanceState zapisał fragmenty w tablicy, która nigdy nie jest czyszczona. Bez wywoływania super, nie zapisuje fragmentów w tych tablicach. – Informatic0re

-1

Wystarczy użyć w viewPager.setonpagechangelistener i wdrożenia dla wymagać zastosowania kodu aplikacji,

http://developer.android.com/reference/android/support/v4/view/ViewPager.html

+0

Już wdrażam OnPageChangeListener, ale nie chcę robić Cała praca tam jest. Myślę, że jest tylko pamięć podręczna lub coś, co muszę wyczyścić.Być może z ViewPager lub FragmentManager. Adapter jest całkowicie nowy, ViewPage jest r ecreated z findViewById, więc dlaczego coś zapisuje pamięć podręczną? Może to jest savedState, ale nie wiem jak go usunąć. – Informatic0re

0

Wystąpił również ten problem i znalazłem przyczynę.

Kiedykolwiek ekran obraca się, FragmentManager zachowa swoją aktywność wszystkich obsługiwanych fragmenty, wou't To usunąć fragmenty przypadku korzystania FragmentStatePagerAdapter, można użyć FragmentManager.getFragments() aby sprawdzić liczbę fragmentów.

Przykład: Aktywność ma 4 fragmenty, Po 4-krotnej zmianie orientacji, lista o rozmiarze FragmentManager.getFragments() będzie wynosić !

znalazłem kilka rozwiązań:

  1. nie nazywają się super.onSaveInstanceState() was aktywny, ale to nie wydaje się dobrym rozwiązaniem, fragmenty mogą nie uratować i przywrócić stan.

  2. Użyj FragmentPagerAdapter zamiast FragmentStatePagerAdapter. Ale po zmianie orientacji, fragmenty hostowane przez ViewPager były wygaszone (czy ktoś inny ma taki sam problem?). Ale mogę usunąć wszystkie fragmenty w Activity.onCreate, aby to naprawić. tak:

    public void onCreate(Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState); 
        FragmentManager fm = getSupportFragmentManager(); 
        List<Fragment> fragments = fm.getFragments(); 
        if (fragments != null) { 
         FragmentTransaction transaction = fm.beginTransaction(); 
         for (Fragment fragment : fragments) { 
          transaction.detach(fragment).remove(fragment); 
         } 
         transaction.commitNowAllowingStateLoss(); 
        } 
        ... 
    

    Ale Fragment.onCreateView() jest wywoływany dwa razy.

ciągle szukam idealnego rozwiązania: D

Edit:
I wreszcie rozwiązał problem, To przyczyna mojego ViewPager jest dodać po onStart. Po uruchomieniu na onStart, FragmentManager spróbuje przywrócić stan fragmentów. I prześledzić na FragmentManager, mieć te kod:

com/android/support/support-fragment/24.2.1/support-fragment-24.2.1-sources.jar!/android/support/v4/app/FragmentManager.java

sprawdzenie linii podświetlenia The f.mContainerId faktycznie jest mój ViewPager id. Następnie spróbuje dodać widok fragmentów do ViewPagera, w moim przypadku ViewPager nie jest jeszcze dodany, więc będzie wygaszony, ale stan fragmentów to ATTACHED. Aw FragmentPagerAdapter.instantiateItem(), Jeśli fragment został dodany, to po prostu nie attach fragment, jednak fragment jest już podłączony, więc jej zrobić nic :(

dodam ViewPager XML aktywność układu, jego stałe.

Szczęśliwy kodowanie: D

Powiązane problemy