FragmentPagerAdapter getItem nie jest wywoływana

123

Nie mogę ponownie użyć fragmentu w FragmentPagerAdapter .. Używając metody zniszczenia (), usuwa fragment, ale nadal nie wywołuje ponownie getItem (). Są tylko 2-3 obrazy, więc używam FragmentPagerAdapter zamiast FragmentStatePagerAdapter ..

public class ExamplePagerAdapter extends FragmentPagerAdapter {

    ArrayList < String > urls;
    int size = 0;
    public ExamplePagerAdapter(FragmentManager fm, ArrayList < String > res) {
        super(fm);
        urls = res;
        size = urls.size();
    }

    @Override
    public int getCount() {
        if (urls == null) {
            return 0;
        } else {
            return size;
        }

    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        FragmentManager manager = ((Fragment) object).getFragmentManager();
        FragmentTransaction trans = manager.beginTransaction();
        trans.remove((Fragment) object);
        trans.commit();
    }

    @Override
    public Fragment getItem(int position) {

        Fragment fragment = new FloorPlanFragment();
        Bundle b = new Bundle();
        b.putInt("p", position);
        b.putString("image", urls.get(position));
        Log.i("image", "" + urls.get(position));
        fragment.setArguments(b);
        return fragment;
    }
}

I In FragmentActivity,

pager.setAdapter(new ExamplePagerAdapter(getSupportFragmentManager(), res2)); 
Kanika
źródło
3
Czy jest jakiś szczególny powód, dla którego przesadziłeś destroyItem()? To nie jest konieczne.
CommonsWare,
aby ponownie zainicjować, użyj FragmentStatePagerAdapter również wywołaj, gdy go przesłonisz super.destroyItem (kontener, pozycja, obiekt);
faiziii

Odpowiedzi:

306

Odpowiedź KISS:

Proste użycie FragmentStatePagerAdapter zamiast FragmentPagerAdapter .

Dostałem odpowiedź ... Najpierw pomyślałem, że skasuję to pytanie, ponieważ robię bardzo głupi błąd, ale ta odpowiedź pomoże komuś, kto ma ten sam problem, którego Zamiast FragmentPagerAdapterużywać FragmentStatePagerAdapter.

Jak @BlackHatSamurai wspomniał w komentarzu:

Powodem tego jest to, że FragmentStatePagerAdapterniszczy jako fragmenty, które nie są używane. FragmentPagerAdapternie.

Kanika
źródło
Wielkie dzięki. Odpowiedź u mnie bardzo pomogła.
Priya
1
Nienawidzę być kolejnym „ja też!” post, ale tak>. <Dziękuję, że nie usuwasz pytania.
Paul Ruiz,
34
Powodem tego jest to, że FragmentStatePagerAdapter niszczy jako fragmenty, które nie są używane. FragmentPagerAdapter nie.
BlackHatSamurai
3
Tylko jako odniesienie w przyszłości dla tych, którzy mogą to znaleźć, szukając konkretnego problemu; przeczytaj zarówno FragmentPagerAdapter, jak i FragmentStatePagerAdapter. Zachowują się inaczej z jakiegoś powodu, a twoje konkretne użycie może wymagać jednego nad drugim.
Chris Stewart,
2
@najibputhawala Użyłem FragmentStatePagerAdapter, ale wciąż mam ten sam problem. getItem () nie zostało wywołane
sam_k
168

Użycie a FragmentStatePagerAdapternie rozwiązało w pełni mojego problemu, który był podobnym problemem, gdy onCreateViewnie było wywoływanych fragmentów podrzędnych na stronie widoku. Faktycznie zagnieżdżam swoje FragmentPagerAdapterwnętrze w innym,Fragment dlatego FragmentManagerplik był współdzielony przez wszystkie z nich, zachowując w ten sposób wystąpienia starych fragmentów. Rozwiązanie polegało na tym, że zamiast tego przekazano instancję getChildFragmentManagerdo konstruktora FragmentPagerAdapterfragmentu w moim hoście. Coś jak...

FragmentPagerAdapter adapter = new FragmentPagerAdapter(getChildFragmentManager());

getChildFragmentManager()Metoda jest dostępny za pośrednictwem fragmentu i to pracował dla mnie, ponieważ zwraca prywatny FragmentManagerdo tego fragmentu z myślą o sytuacjach, w których konieczne jest zagnieżdżanie fragmenty. Mam nadzieję, że pomoże to komuś, kto może mieć ten sam problem co ja !!

  • Pamiętaj jednak, że aby użyć getChildFragmentManager()minimalnej wersji API, musi być co najmniej 17 (4.2), więc może to rzucić kluczem w twoje koła zębate. Oczywiście, jeśli używasz fragmentów z biblioteki wsparcia v4, powinieneś być w porządku.
Jraco11
źródło
25
To jest poprawna odpowiedź. Problem polega na tym, że fragmenty zagnieżdżone w innych fragmentach powinny używać metody getChildrenFragmentManager () zamiast metody getFragmentManager ().
shihpeng
Dziękuję bardzo, znalezienie tej odpowiedzi zajęło mi wieczność!
Shpongoloid
Zgadzam się z @shihpeng. To powinna być prawidłowa odpowiedź.
Raymond Lukanta,
Ten był dla mnie poprawką.
Wielkie
Doktorzy powinni naprawdę to opisać na spacerze. Jest wysoce realistyczne, że ViewPager zostanie załadowany we fragmencie. Dzięki za opublikowanie tej odpowiedzi.
pracował
7

Nadpisanie long getItemId (int position)

FragmentPagerAdapterbuforuje utworzone przez siebie fragmenty za pomocą getItem. Miałem ten sam problem - nawet po telefonienotifyDataSetChanged() getItem nie .

W rzeczywistości jest to funkcja, a nie błąd. Musisz nadpisać getItemId, aby móc poprawnie ponownie wykorzystać swoje fragmenty. Ponieważ usuwasz fragmenty, twoje pozycje się zmieniają. Jak wspomniano w dokumentach:

long getItemId (int position)

Zwróć unikalny identyfikator dla pozycji na danej pozycji.

Domyślna implementacja zwraca podaną pozycję. Podklasy powinny zastępować tę metodę, jeśli pozycje elementów mogą się zmienić.

Po prostu podaj unikalny identyfikator dla każdego fragmentu i gotowe.

Używanie FragementStatePagerAdapterlub powrotu POSITION_NONEw int getItemPosition (Object object)to źle. Nie otrzymasz żadnego buforowania.

vedant
źródło
To była poprawna odpowiedź. Musiałem podać różne identyfikatory dla fragmentów w getItemIdAND dostosować, getItemPositionaby zwrócić, POSITION_NONEJEŚLI fragment powinien zostać usunięty. Mam do tego flagę wyliczenia. Po tym getItemzostanie wywołany.
Murat Karagöz
Dziękuję @ MuratKaragöz za +50 :)
vedant
5

Zrobiłem to, co opublikowali @kanika i @ Jraco11, ale nadal miałem problem.

Tak więc po wielu zmianach znalazłem taki, który działał dla mnie i został dodany do mojego FragmentPagerAdapter z następnym kodem:

    @Override
    public int getItemPosition(Object object) {
        return POSITION_NONE;
    }

Zgodnie z tym, co przeczytałem, getItemPosition służy do powiadamiania ViewPagera, czy odświeżyć element, oraz do uniknięcia aktualizacji, jeśli elementy w widocznych pozycjach nie uległy zmianie.

Jorge Casariego
źródło
2

Istnieją dwa różne scenariusze: 1.) Masz taki sam układ dla każdego pagera: w takim przypadku będzie lepiej, jeśli rozszerzysz swój niestandardowy adapter o PagerAdapter i zwrócisz pojedynczy układ.

2.) Masz inny układ dla każdego pagera: w takim przypadku będzie lepiej, jeśli rozszerzysz swój niestandardowy adapter o FragmentStatePagerAdapter i zwrócisz różne fragmenty dla każdego pagera.

Maddy
źródło
2

Metoda getItem()służy tylko do tworzenia nowych pozycji. Po utworzeniu ta metoda nie zostanie wywołana. Jeśli chcesz uzyskać przedmiot, który jest walutą używaną przez adapter, użyj tej metody:

pagerAdapter.instantiateItem(viewPager, TAB_POS)
B-GangsteR
źródło
0

Zauważyłem, że ustawienie listenera w układzie tabulatora uniemożliwiło wywołanie tego, prawdopodobnie dlatego, że mają miejsce tylko dla jednego słuchacza tabLayout.setOnTabSelectedListenerzamiast tablicy słuchaczy.

Oliver Dixon
źródło