FragmentPagerAdapter getItem tidak dipanggil

123

Saya tidak dapat menggunakan kembali fragmen di FragmentPagerAdapter .. Menggunakan metode destroyItem (), Ini menghapus fragmen tetapi masih tidak memanggil getItem () lagi..Hanya ada 2-3 Gambar jadi saya menggunakan FragmentPagerAdapter, bukan 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;
    }
}

Dan Di FragmentActivity,

pager.setAdapter(new ExamplePagerAdapter(getSupportFragmentManager(), res2)); 
Kanika
sumber
3
Apakah ada alasan khusus Anda mengesampingkan destroyItem()? Itu tidak perlu.
CommonsWare
untuk menginisialisasi lagi gunakan FragmentStatePagerAdapter, juga panggil saat Anda menimpanya super.destroyItem (container, position, object);
faiziii

Jawaban:

306

KISS Jawaban:

Gunakan FragmentStatePagerAdapter secara sederhana, bukan FragmentPagerAdapter .

Saya mendapat jawabannya .. Pertama saya berpikir untuk menghapus pertanyaan ini karena saya melakukan kesalahan yang sangat konyol tetapi jawaban ini akan membantu seseorang yang menghadapi masalah yang sama daripada FragmentPagerAdaptermenggunakan FragmentStatePagerAdapter.

Seperti yang disebutkan @BlackHatSamurai di komentar:

Alasan ini berhasil adalah karena FragmentStatePagerAdaptermenghancurkan sebagai Fragmen yang tidak digunakan. FragmentPagerAdaptertidak.

Kanika
sumber
Terima kasih banyak Jawaban Anda banyak membantu saya.
Priya
1
Benci menjadi 'aku juga!' posting, tapi ya>. <Terima kasih telah tidak menghapus pertanyaan.
Paul Ruiz
34
Alasan ini berfungsi adalah karena FragmentStatePagerAdapter dihancurkan sebagai Fragmen yang tidak digunakan. FragmentPagerAdapter tidak.
BlackHatSamurai
3
Hanya untuk referensi di masa mendatang bagi mereka yang mungkin menemukan ini saat mencari masalah khusus yang mereka hadapi; baca di FragmentPagerAdapter dan FragmentStatePagerAdapter. Mereka berperilaku berbeda karena suatu alasan dan penggunaan khusus Anda mungkin memerlukan salah satu dari yang lainnya.
Chris Stewart
2
@najibputhawala Saya menggunakan FragmentStatePagerAdapter tetapi masih menghadapi masalah yang sama. getItem () tidak dipanggil
sam_k
168

Menggunakan sebuah FragmentStatePagerAdapter tidak sepenuhnya memperbaiki masalah saya yang merupakan masalah serupa di mana onCreateViewtidak dipanggil untuk fragmen anak di halaman tampilan. Saya benar-benar menumpuk FragmentPagerAdapterdi dalam saya yang lainFragment karena FragmentManageritu dibagikan di semua dari mereka dan dengan demikian mempertahankan contoh dari fragmen lama. Perbaikannya adalah dengan memberi makan sebuah instance dari getChildFragmentManagerke konstruktor di FragmentPagerAdapterdalam fragmen host saya. Sesuatu seperti...

FragmentPagerAdapter adapter = new FragmentPagerAdapter(getChildFragmentManager());

The getChildFragmentManager()Metode dapat diakses melalui fragmen dan ini bekerja untuk saya karena mengembalikan swasta FragmentManageruntuk fragmen yang khusus untuk situasi di mana fragmen bersarang diperlukan. Saya harap ini membantu seseorang yang mungkin mengalami masalah yang sama dengan saya !!

  • Namun perlu diingat untuk menggunakan getChildFragmentManager() versi API minimum Anda harus minimal 17 (4.2), jadi ini dapat membuang kunci pas di gigi Anda. Tentu saja, jika Anda menggunakan fragmen dari support library v4 Anda akan baik-baik saja.
Jraco11
sumber
25
Ini jawaban yang benar. Masalahnya adalah fragmen yang disarangkan di fragmen lain harus menggunakan getChildrenFragmentManager (), bukan getFragmentManager ().
shihpeng
Terima kasih banyak, saya butuh waktu lama untuk menemukan jawaban ini!
Shpongoloid
Saya setuju dengan @shihpeng. Ini harus menjadi jawaban yang benar.
Raymond Lukanta
Yang ini adalah perbaikan bagi saya. Terima kasih banyak telah mengirimkan jawaban
pengguna3734429
Dokumen harus benar-benar menyebutkan hal ini saat berjalan-jalan. Sangat realistis bahwa ViewPager akan dimuat dalam sebuah fragmen. Terima kasih telah memposting jawaban ini.
bekerja
7

Mengesampingkan long getItemId (int position)

FragmentPagerAdaptermenyimpan cache fragmen yang dibuatnya menggunakan getItem. Saya menghadapi masalah yang sama - bahkan setelah meneleponnotifyDataSetChanged() getItem tidak dipanggil.

Ini sebenarnya adalah fitur dan bukan bug. Anda perlu mengganti getItemIdagar Anda dapat menggunakan kembali fragmen Anda dengan benar. Karena Anda menghapus fragmen, posisi Anda berubah. Seperti yang disebutkan dalam dokumen:

long getItemId (int position)

Kembalikan pengenal unik untuk item di posisi tertentu.

Implementasi default mengembalikan posisi yang diberikan. Subclass harus mengganti metode ini jika posisi item dapat berubah.

Cukup berikan id unik untuk setiap fragmen dan Anda selesai.

Menggunakan FragementStatePagerAdapteratau kembali POSITION_NONEdi int getItemPosition (Object object)salah. Anda tidak akan mendapatkan cache apa pun.

vedant
sumber
Yang ini adalah jawaban yang benar. Saya harus memberikan id yang berbeda untuk fragmen di getItemIdDAN menyesuaikan getItemPositionuntuk mengembalikan POSITION_NONEJIKA fragmen harus dihapus. Saya memiliki bendera enum untuk itu. Setelah itu getItemakan dipanggil.
Murat Karagöz
Terima kasih @ MuratKaragöz untuk +50 :)
vedant
5

Saya melakukan apa yang telah diposting @kanika dan @ Jraco11 tetapi saya masih mengalami masalah.

Jadi, setelah banyak perubahan, saya menemukan satu yang berfungsi untuk saya dan ditambahkan ke FragmentPagerAdapter saya kode berikutnya:

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

Menurut apa yang saya baca, getItemPosition digunakan untuk memberi tahu ViewPager apakah akan menyegarkan item atau tidak, dan untuk menghindari pembaruan jika item pada posisi yang terlihat tidak berubah.

Jorge Casariego
sumber
2

Ada dua skenario berbeda: 1.) Anda memiliki tata letak yang sama untuk setiap pager: Dalam hal ini, akan lebih baik jika Anda memperluas adaptor khusus Anda dengan PagerAdapter dan mengembalikan satu tata letak.

2.) Anda memiliki tata letak yang berbeda untuk setiap halaman: Dalam hal ini, akan lebih baik jika Anda memperluas adaptor kustom Anda dengan FragmentStatePagerAdapter dan mengembalikan fragmet yang berbeda untuk setiap halaman.

Maddy
sumber
2

metode getItem()digunakan hanya untuk membuat item baru. Setelah dibuat, metode ini tidak akan dipanggil. Jika Anda perlu mendapatkan item mata uang yang digunakan oleh adaptor, gunakan metode ini:

pagerAdapter.instantiateItem(viewPager, TAB_POS)
B-GangsteR
sumber
0

Saya menemukan bahwa menyetel listener pada tab-layout menghentikan pemanggilan ini, mungkin karena mereka hanya memiliki ruang untuk satu listener di tabLayout.setOnTabSelectedListeneralih-alih array listener.

Oliver Dixon
sumber