2012-05-13 10 views
9

Mam problem z odwoływaniem się do moich fragmentów wewnątrz ViewPager. Chciałbym to zrobić, ponieważ z mojej działalności chciałbym odświeżyć fragment w określonej pozycji (np. Aktualnie wyświetlany fragment).Odwoływanie się do Fragmenty wewnątrz ViewPager

Obecnie mam coś takiego:

public static class MyPagerAdapter extends FragmentPagerAdapter { 

    private static final String TAG = "MyPagerAdapter"; 
    private static HashMap<Integer, EventListFragment> mPageReferenceMap = new HashMap<Integer, EventListFragment>(); 

    public MyPagerAdapter(FragmentManager fm) { 
     super(fm); 
    } 

    @Override 
    public int getCount() { 
     return NUM_ITEMS; 
    } 

    @Override 
    public Fragment getItem(int position) { 
     Log.i(TAG, "getItem: "+position); 
     int dateOffset = position-1; 
     EventListFragment mFragment = EventListFragment.newInstance(dateOffset); 
     mPageReferenceMap.put(position, mFragment); 
     return mFragment; 
    } 

    @Override 
    public void destroyItem(ViewGroup container, int position, Object object) { 
     Log.i(TAG, "destroyItem: "+position); 
     mPageReferenceMap.remove(position); 
     super.destroyItem(container, position, object); 
    } 


    public EventListFragment getFragment(int key) { 
     Log.i(TAG, "Size of pager references: "+mPageReferenceMap.size()); 
     return mPageReferenceMap.get(key); 
    } 
} 

Problem polega na tym, że destroyItem() jest wywoływana częściej niż getItem(), więc pozostaje mi referencji null. Jeśli nie używam destroyItem() do usuwania odniesień do zniszczonych fragmentów ... cóż, odwołuję się do fragmentów, które nie istnieją.

Czy istnieje jakiś dobry sposób odniesienia fragmentów, które są tworzone z EventListFragment mFragment = EventListFragment.newInstance(dateOffset);? Albo co zrobić, aby odświeżyć fragment wewnątrz ViewPagera z mojej aktywności (z menu opcji, by być precyzyjnym)?

Odpowiedz

5

Udało mi się go rozwiązać. Sztuką było stworzenie listy referencyjnej w Activity, a nie PagerAdapter. To idzie tak:

List<WeakReference<EventListFragment>> fragList = new ArrayList<WeakReference<EventListFragment>>(); 

@Override 
public void onAttachFragment (Fragment fragment) { 
    Log.i(TAG, "onAttachFragment: "+fragment); 
    if(fragment.getClass()==EventListFragment.class){ 
     fragList.add(new WeakReference<EventListFragment>((EventListFragment)fragment)); 
    } 
} 
public EventListFragment getFragmentByPosition(int position) { 

    EventListFragment ret = null; 
    for(WeakReference<EventListFragment> ref : fragList) { 
     EventListFragment f = ref.get(); 
     if(f != null) { 
      if(f.getPosition()==position){ 
       ret = f; 
      } 
     } else { //delete from list 
      fragList.remove(f); 
     } 
    } 
    return ret; 

} 

Oczywiście Twój fragment musi wdrożyć getPosition() funkcję, ale potrzebowałem czegoś takiego w każdym razie, więc to nie był problem.

Dzięki Alex Lockwood za Twoją sugestię z WeakReference!

+0

Właśnie skończyłem moje finały i postanowiłem wrócić i zobaczyć, czy masz działające rzeczy ... cieszę się, że mogłem pomóc (nawet jeśli nie było to z głównym problemem: P). –

+0

Pytanie: czy nie powinno się przekazywać wywołania fragList.remove() słabego odwołania, a nie fragmentu? – gcl1

+0

@Michael: Zacząłem używać takiego podejścia i działa całkiem nieźle. Ale ponieważ fragList zawiera słabe referencje, wydaje się, że wpisy podlegają wyrzucaniu śmieci, nawet jeśli nadal ich potrzebujesz. Widziałem, że metoda getFragmentByPosition() czasami zwraca wartość null, więc myślę, że to właśnie się dzieje. Jakieś pomysły, jak sobie z tym poradzić? Dzięki. – gcl1

3

dwie rzeczy:

  1. dodaj następującą linię w swoim onCreate Przebieg ćwiczenia (lub gdziekolwiek zainicjować ViewPager):

    mPager.setOffscreenPageLimit(NUM_ITEMS-1); 
    

    to zachowa dodatkowych off ekranie stron w pamięci (tj. uniemożliwiając ich zniszczenie), nawet jeśli nie są one aktualnie wyświetlane na ekranie.

  2. Można rozważyć wdrożenie swój HashMap tak, że posiada WeakReference<Fragment> s zamiast Fragment s sami. Należy pamiętać, że będzie to wymagać, aby zmienić metodę getFragment następująco:

    WeakReference<Fragment> weakRef = mPageReferenceMap.get(position); 
    return (weakRef != null) ? weakRef.get() : null; 
    

    To nie ma nic wspólnego z Twoim problemem ... to jest po prostu coś zauważyłem i że chciałbym zwrócić uwagę. Przechowywanie WeakReferences dla twojego Fragment s pozwoli ci wykorzystać zdolność odśmiecacza do określenia osiągalności dla ciebie, więc nie musisz tego robić sam.

+0

Jeśli chodzi o 2. => to nie rozwiąże mojego problemu, ale jest to prawdopodobnie dobry pomysł, aby zapobiec wyciekom, dziękuję. I 1. => Będę miał 7 stron, może więcej w przyszłości, czy można przechowywać je wszystkie w pamięci w tym samym czasie? –

+0

Hmm ... oczywiście, im mniej 'Fragmentu 'trzymasz w pamięci, tym lepiej. Jeśli chcesz uzyskać dostęp do 'Fragmentu' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' 'Activity'' (bez przełączania się na stronę' Fragment') bez zachowania ich w pamięci, poprawka byłaby trudniejsza. Może to wymagać zagłębienia się w kod źródłowy 'ViewPager' i zobaczenie, jak obsługuje on cykl życia' Fragment'. Nie jestem świadomy, jak to zrobić, ale zajrzę do niego, gdy będę mieć więcej czasu. –

+0

Mogę pokornie zasugerować, że jeśli jest coś, co musisz dostać z Fragmentu, gdy jest poza ekranem, może nie powinieneś podawać go Fragmentowi.Rozważ umieszczenie go w usłudze lub dostawcy treści, a Twój Fragment będzie klientem. – Sparky

Powiązane problemy