2012-09-03 21 views
8

Mam ViewPager (rozszerza FragmentPagerAdapter), który przechowuje dwa Fragments. To, czego potrzebuję, to odświeżenie ListView dla każdego Fragment podczas przesuwania między nimi. W tym celu zaimplementowałem interfejs ViewPager.OnPageChangeListener (a mianowicie onPageScrollStateChanged). W celu przechowywania odniesień do Fragment s używam HashTable. Przechowywać odnośniki do Fragments w HashTable w getItem() metody:FragmentPagerAdapter nie odtwarza fragmentów po zmianie orientacji?

@Override 
     public Fragment getItem(int num) { 
      if (num == 0) { 
       Fragment itemsListFragment = new ItemsListFragment(); 
       mPageReferenceMap.put(num, itemsListFragment); 
       return itemsListFragment; 
      } else { 
       Fragment favsListFragment = new ItemsFavsListFragment(); 
       mPageReferenceMap.put(num, favsListFragment); 
       return favsListFragment; 
      } 
     } 

Więc kiedy trzepnąć z jednego Fragment drugiemu onPageScrollStateChanged wyzwala gdzie używam HashTable zadzwonić wymaganej metody zarówno Fragments (Odśwież):

public void refreshList() { 
     ((ItemsListFragment) mPageReferenceMap.get(0)).refresh(); 
     ((ItemsFavsListFragment) mPageReferenceMap.get(1)).refresh(); 
    } 

Wszystko idzie dobrze, aż dojdzie do zdarzenia orientation change. Po to kod w refresh() metody, która jest:

public void refresh() { 
     mAdapter.changeCursor(mDbHelper.getAll()); 
     getListView().setItemChecked(-1, true); // The last row from a exception trace finishes here (my class). 
    } 

skutkuje IllegalStateException:

java.lang.IllegalStateException: Content view not yet created 
     at android.support.v4.app.ListFragment.ensureList(ListFragment.java:328) 
     at android.support.v4.app.ListFragment.getListView(ListFragment.java:222) 
     at ebeletskiy.gmail.com.passwords.ui.ItemsFavsListFragment.refresh(ItemsFavsListFragment.java:17) 

Zakładając widok Content nie jest tworzona faktycznie ustawić zmienną boolean w onActivityCreated() metody true i używane if/else warunek wywołania getListView() lub nie, który pokazał pomyślne utworzenie widoku aktywności i treści.

Następnie debugowałem, aby zobaczyć, kiedy FragmentPagerAdapter wywołuje getItem() i zdarza się, że metoda nie jest wywoływana po zdarzeniu orientation change. Wygląda na to, że ViewPager zawiera odniesienia do starego Fragments. To tylko moje założenie.

Czy jest jakiś sposób na wymuszenie ViewPager, aby ponownie zadzwonić pod numer getItem(), więc mogę użyć odpowiednich odniesień do bieżącego Fragments? Może być jakieś inne rozwiązanie? Dziękuję Ci bardzo.

Odpowiedz

4

Potem został debugowanie aby zobaczyć, kiedy FragmentPagerAdapter wywołuje GetItem(), a zdarza się, metoda ta jest wywoływana po zmianie orientacji imprezy. Wygląda na to, że ViewPager zawiera odniesienia do starych Fragmentów.

Fragmenty powinny być automatycznie odtwarzane, tak jak każdy fragment jest na zmianie konfiguracji. Wyjątkiem byłoby użycie nazwy setRetainInstance(true), w którym to przypadku powinny to być te same obiekty fragmentów, co poprzednio.

Czy istnieje sposób na egzekwowanie funkcji ViewPager, aby ponownie wywołać metodę getItem(), aby można było używać odpowiednich odniesień do bieżących fragmentów?

Co jest nie tak z fragmentami, które tam są?

+0

Nie używam tutaj 'setRetainInstance()'. Problem dotyczy wyjątku, który pojawia się po "zmianie orientacji". Po prostu przyjmuję, że stare Fragmenty są w użyciu, ponieważ sprawdziłem warunek, że dla obu jest wykonywana metoda 'onActivityCreated()'. – Eugene

+0

@siik: Kiedy wywołujesz tę metodę 'refresh()'? A kiedy wyciągasz nowo utworzone fragmenty, aby zapełnić (ick) 'Hashtable'? – CommonsWare

+0

Wywołuję tę metodę 'refresh()' w 'onPageScrollStateChanged()' (która jest implementacją interfejsu 'ViewPager.OnPageChangeListener', tj. Gdy przeskakuję pomiędzy' Fragmentami'). I zapełniam 'HashTable' w metodzie' getItem() 'klasy która rozszerza' FragmentPagerAdapter' – Eugene

0

Spędziłem kilka dni w poszukiwaniu rozwiązania tego problemu, a wiele punktów został zorientowali się:

  • użycie FragmentPagerAdapter zamiast FragmentStatePagerAdapter

  • użycie FragmentStatePagerAdapter zamiast FragmentPagerAdapter

  • return POSITION_NONE na getItemPosition zastąpienie FragmentPagerAdapter

  • nie używać FragmentPagerAdapter jeśli trzeba dynamiczne zmiany fragmentów

  • i wiele wiele wiele innych ...

W mojej aplikacji, jak Eugene udało mi sobie przypadki stworzony paprochy. Przechowuję to w jednym HashMap<String,Fragment> wewnątrz pewnej specjalistycznej klasy, więc fragmenty nigdy nie są wypuszczane, co przyspiesza moją aplikację (ale pochłania więcej zasobów).

Problem polegał na tym, że obracam tabletem (i telefonem). The getItem(int) nie był już nazywany tym fragmentem i nie mogłem go zmienić.

naprawdę spędził wiele czasu, aż naprawdę znalazł rozwiązanie, więc muszę podzielić się nim ze społecznością StackOverflow, który pomaga mi tak wiele razy ...

rozwiązanie tego problemu, pomimo ciężkiej pracy go znaleźć, jest dość prosta:

Wystarczy zachować odniesienie do FragmentManager w konstruktorze FragmentPagerAdapter rozciąga:

public class Manager_Pager extends FragmentPagerAdapter { 

    private final FragmentManager mFragmentManager; 
    private final FragmentActivity mContext; 

    public Manager_Pager(FragmentActivity context) { 

     super(context.getSupportFragmentManager()); 

     this.mContext = context; 
     this.mFragmentManager = context.getSupportFragmentManager(); 
    } 

    @Override 
    public int getItemPosition(Object object) { 

// here, check if this fragment is an instance of the 
// ***FragmentClass_of_you_want_be_dynamic*** 

     if (object instanceof FragmentClass_of_you_want_be_dynamic) { 

// if true, remove from ***FragmentManager*** and return ***POSITION_NONE*** 
// to force a call to ***getItem*** 

      mFragmentManager.beginTransaction().remove((Fragment) object).commit(); 
      return POSITION_NONE; 
     } 

     //don't return POSITION_NONE, avoid fragment recreation. 
     return super.getItemPosition(object); 
    } 

    @Override 
    public Fragment getItem(int position) { 


     if (position == MY_DYNAMIC_FRAGMENT_INDEX){ 

      Bundle args = new Bundle(); 
      args.putString("anything", position); 
      args.putString("created_at", ALITEC.Utils.timeToStr()); 

      return Fragment.instantiate(mContext, FragmentClass_of_you_want_be_dynamic.class.getName(), args); 

     }else 

     if (position == OTHER){ 

      //... 

     }else 

     return Fragment.instantiate(mContext, FragmentDefault.class.getName(), null); 

    } 
} 

to wszystko. I będzie działać jak urok ...

+1

to nie działa dla mnie getItem nigdy nie wywołaj zmiany orientacji. – JosephM

+0

this.mFragmentManager = context.getSupportFragmentManager(); – alijunior

Powiązane problemy