Apa perbedaan antara FragmentPagerAdapter dan FragmentStatePagerAdapter?

375

Apa perbedaan antara FragmentPagerAdapterdan FragmentStatePagerAdapter?

Tentang FragmentPagerAdapterpanduan Google mengatakan:

Versi pager ini terbaik untuk digunakan ketika ada beberapa fragmen statis yang lebih umum untuk di-paging, seperti seperangkat tab. Fragmen setiap halaman yang dikunjungi pengguna akan disimpan dalam memori, meskipun hierarki tampilan dapat dihancurkan saat tidak terlihat. Ini dapat mengakibatkan penggunaan jumlah memori yang signifikan karena instance fragmen dapat bertahan pada jumlah negara yang sewenang-wenang. Untuk set halaman yang lebih besar, pertimbangkan FragmentStatePagerAdapter.

Dan tentang FragmentStatePagerAdapter:

Versi pager ini lebih berguna ketika ada banyak halaman, bekerja lebih seperti tampilan daftar. Ketika halaman tidak terlihat oleh pengguna, seluruh fragmennya dapat dihancurkan, hanya menjaga keadaan yang disimpan dari fragmen itu. Hal ini memungkinkan pager untuk mempertahankan memori yang jauh lebih sedikit terkait dengan setiap halaman yang dikunjungi dibandingkan dengan FragmentPagerAdapterbiaya yang berpotensi lebih tinggi saat beralih antar halaman.

Jadi saya hanya memiliki 3 fragmen. Tetapi semuanya merupakan modul terpisah dengan sejumlah besar data.

Fragment1menangani beberapa data (yang dimasukkan pengguna) dan meneruskannya melalui aktivitas Fragment2, yang hanya sederhana ListFragment. Fragment3juga a ListFragment.

Jadi pertanyaan saya adalah : Adaptor mana yang harus saya gunakan? FragmentPagerAdapteratau FragmentStatePagerAdapter?

AlexMomotov
sumber
2
Saya pikir hanya memiliki 3 Fragmen yang memenuhi syarat Anda untuk menggunakan FragmentPagerAdapter. Tab untuk Fragmen-fragmen ini mungkin semua akan terlihat secara bersamaan.
IgorGanapolsky
2
posting ini menghemat 5-6 jam saya karena saya menggunakan jenis Adaptor yang salah
Nantaphop
1
Jawaban untuk pertanyaan ini melemparkan satu pertanyaan lagi stackoverflow.com/questions/9156406/…
Piyush Kukadiya
ada FragmentPagerAdapterdan FragmentStatePagerAdaptertetapi apa itu FragmentStateAdapter?
the_prole

Jawaban:

292

Seperti kata docs, pikirkan seperti ini. Jika Anda melakukan aplikasi seperti pembaca buku, Anda tidak akan ingin memuat semua fragmen ke dalam memori sekaligus. Anda ingin memuat dan memusnahkan Fragmentssaat pengguna membaca. Dalam hal ini yang akan Anda gunakan FragmentStatePagerAdapter. Jika Anda hanya menampilkan 3 "tab" yang tidak mengandung banyak data berat (seperti Bitmaps), FragmentPagerAdaptermungkin cocok untuk Anda. Perlu diingat juga bahwa ViewPagersecara default akan memuat 3 fragmen ke dalam memori. Yang pertama AdapterAnda sebutkan mungkin menghancurkan Viewhierarki dan memuatnya kembali saat diperlukan, yang kedua Adapterhanya menyimpan keadaan Fragmentdan benar-benar menghancurkannya, jika pengguna kemudian kembali ke halaman itu, keadaan diambil.

Emmanuel
sumber
Saya memiliki beberapa Tombol dan TextViews di Fragment1 dan ListView yang menghasilkan item secara dinamis di Fragment2 dan Fragment3. Apakah Anda pikir itu ide yang baik untuk menggunakan FragmentStatePagerAdapter dan menyimpan semua data dalam Activity, meneruskannya ke Fragments via Bundle?
AlexMomotov
2
@AlexMomotov Tampilan dalam tata letak Fragment tidak ada hubungannya dengan pilihan FragmentStatePagerAdapter. Pertanyaannya di sini adalah jumlah Fragmen yang akan ditelusuri.
IgorGanapolsky
1
Jadi pada dasarnya tidak ada yang mendukung FragmentPagerAdapteruntuk menggunakannya.
Tomasz Mularczyk
3
@ Thomasz keuntungan dari FragmentPagerAdapterberalih antar fragmen bisa jauh lebih cepat, karena Fragmentobjek yang sebenarnya tidak perlu dibangun kembali setiap kali. Di sisi lain, ini akan berakhir dengan menggunakan lebih banyak memori yang memegang objek fragmen dalam memori.
Richard Le Mesurier
Saya memiliki 3 tab / halaman (yang masing-masing menampilkan WebView), jadi saya telah menggunakan FragmentPagerAdapter . Namun, halaman terakhir masih digambar ulang saat saya menggeser ke sana dari halaman pertama. Untuk mengatasi ini, saya telah menggunakan viewPager.setOffscreenPageLimit(2).
larangan geoengineering
131
  • FragmentPagerAdaptermenyimpan seluruh fragmen dalam memori, dan dapat meningkatkan overhead memori jika sejumlah besar fragmen digunakan ViewPager.

  • Sebaliknya saudaranya, FragmentStatePagerAdapterhanya menyimpan keadaan Instance dari fragmen, dan menghancurkan semua fragmen ketika mereka kehilangan fokus.

  • Karena itu FragmentStatePagerAdapterharus digunakan ketika kita harus menggunakan fragmen dinamis, seperti fragmen dengan widget, karena data mereka dapat disimpan dalam savedInstanceState. Juga tidak akan mempengaruhi kinerja bahkan jika ada sejumlah besar fragmen.

  • Sebaliknya saudara kandungnya FragmentPagerAdapterharus digunakan ketika kita perlu menyimpan seluruh fragmen dalam memori.

  • Ketika saya mengatakan seluruh fragmen disimpan dalam memori artinya, instansnya tidak akan dihancurkan dan akan membuat overhead memori. Oleh karena itu disarankan untuk digunakan FragmentPagerAdapterhanya ketika ada jumlah fragmen yang rendah ViewPager.

  • Akan lebih baik jika fragmennya statis, karena mereka tidak akan memiliki sejumlah besar objek yang instansnya akan disimpan.

Untuk lebih detail,

FragmentStatePagerAdapter:

  • dengan FragmentStatePagerAdapter, fragmen yang tidak dibutuhkan Anda dihancurkan. Transaksi berkomitmen untuk sepenuhnya menghapus fragmen dari aktivitas Anda FragmentManager.

  • Status dalam FragmentStatePagerAdapterberasal dari fakta bahwa itu akan menyelamatkan fragmen Anda Bundledari savedInstanceStatesaat dihancurkan. Ketika pengguna menavigasi kembali, fragmen baru akan dipulihkan menggunakan keadaan fragmen itu.

FragmentPagerAdapter:

  • Dengan perbandingan FragmentPagerAdaptertidak melakukan hal semacam itu. Ketika fragmen tidak lagi diperlukan. FragmentPagerAdapterpanggilan detach(Fragment)pada transaksi, bukan remove(Fragment).

  • Ini menghancurkan pandangan fragmen tetapi membiarkan instance fragmen hidup di FragmentManager. Jadi fragmen yang dibuat di FragmentPagerAdaptertidak pernah dihancurkan.

Steve
sumber
2
Mengapa Anda punya 2 jawaban?
Jared Burrows
apa manfaat menyimpan seluruh fragmen dalam ingatan?
Tomasz Mularczyk
4
@ Tomek: jika fragmen berikutnya sudah instantiated (yaitu FragmentPagerAdapter), itu akan siap untuk di-render ketika Anda menggeseknya, sehingga animasi swipe akan lebih lancar. Dengan FragmentStatePagerAdapter, instance fragmen berikutnya mungkin tidak ada sampai Anda menggeseknya, dan jika itu adalah fragmen besar yang mahal untuk dibuat, Anda mungkin melihat gagap dalam animasi. Ini masalah kinerja vs konsumsi memori.
Dalbergia
1
@Jared Burrows karena satu hanya AnswerText yang baik untuk jawaban yang kecil dan statis dan yang lainnya adalah AnswerStateText yang untuk jawaban yang lebih besar dan dinamis
Simple Fellow
48

Berikut adalah siklus hidup log masing-masing fragmen ViewPageryang memiliki 4 fragmen danoffscreenPageLimit = 1 (default value)

FragmentStatePagerAdapter

Pergi ke Fragment1 (aktivitas peluncuran)

Fragment1: onCreateView
Fragment1: onStart
Fragment2: onCreateView
Fragment2: onStart

Pergi ke Fragment2

Fragment3: onCreateView
Fragment3: onStart

Pergi ke Fragment3

Fragment1: onStop
Fragment1: onDestroyView
Fragment1: onDestroy
Fragment1: onDetach
Fragment4: onCreateView
Fragment4: onStart

Pergi ke Fragment4

Fragment2: onStop
Fragment2: onDestroyView
Fragment2: onDestroy

FragmentPagerAdapter

Pergi ke Fragment1 (aktivitas peluncuran)

Fragment1: onCreateView
Fragment1: onStart
Fragment2: onCreateView
Fragment2: onStart

Pergi ke Fragment2

Fragment3: onCreateView
Fragment3: onStart

Pergi ke Fragment3

Fragment1: onStop
Fragment1: onDestroyView
Fragment4: onCreateView
Fragment4: onStart

Pergi ke Fragment4

Fragment2: onStop
Fragment2: onDestroyView

Kesimpulan : FragmentStatePagerAdapterpanggil onDestroysaat Fragmen diatasi offscreenPageLimitsementara FragmentPagerAdaptertidak.

Catatan : Saya pikir kita harus menggunakan FragmentStatePagerAdapteruntuk ViewPageryang memiliki banyak halaman karena itu akan bagus untuk kinerja.

Contoh dari offscreenPageLimit:

Jika kita masuk ke Fragment3, itu akan menghancurkan Fragment1 (atau Fragment5 jika ada) karena offscreenPageLimit = 1. Jika kita atur offscreenPageLimit > 1itu tidak akan hancur.
Jika dalam contoh ini, kita atur offscreenPageLimit=4, tidak ada perbedaan antara menggunakan FragmentStatePagerAdapteratau FragmentPagerAdapterkarena Fragmen tidak pernah memanggil onDestroyViewdan onDestroyketika kita mengubah tab

Github demo di sini

Phan Van Linh
sumber
Cara kesimpulan yang hebat!
Rahul Rastogi
penjelasan yang bagus
gourav singhal
1
Penjelasan yang bagus. Anda mengatakan bahwa menggunakan FragmentStatePagerAdapter ketika memiliki banyak halaman bagus untuk kinerja. Apakah maksud Anda itu baik untuk menghemat memori? Tujuannya seperti yang saya pahami adalah untuk melestarikan memori dalam kasus kemungkinan banyak instance Fragmen - jadi kinerja adalah manfaat implisit; tujuan eksplisitnya adalah untuk melestarikan memori
Hatzil
38

Sesuatu yang tidak secara eksplisit dikatakan dalam dokumentasi atau dalam jawaban di halaman ini (meskipun tersirat oleh @Naruto), adalah yang FragmentPagerAdaptertidak akan memperbarui Fragmen jika data dalam Fragmen berubah karena menyimpan Fragmen dalam memori.

Jadi, bahkan jika Anda memiliki jumlah Fragmen terbatas untuk ditampilkan, jika Anda ingin dapat menyegarkan fragmen Anda (misalnya, Anda menjalankan kembali kueri untuk memperbarui listView dalam Fragmen), Anda perlu menggunakan FragmentStatePagerAdapter.

Seluruh poin saya di sini adalah bahwa jumlah Fragmen dan apakah mereka mirip atau tidak tidak selalu merupakan aspek kunci untuk dipertimbangkan. Apakah fragmen Anda dinamis atau tidak juga penting.

JDenais
sumber
Jadi misalkan saya punya 2 fragmen, 1 recyclerview di fragmen A, ketika saya klik pada item itu mengubah konten fragmen B, katakan saya melakukan fragB.setText ("blablabla"). Saya harus menggunakan negara bagian?
Ced
Tidak yakin tetapi saya akan mengatakan ya. Coba saja keduanya, sangat mudah dan cepat untuk mengubah kode Anda dari satu ke yang lain.
JDenais
@JDenais Anda yakin ini benar? Saya menggunakan FragmentPagerAdapterdalam aktivitas saya yang menggunakan ViewPager untuk menampilkan dua fragmen - di mana setiap fragmen berisi daftar. Daftar pertama saya disebut "Semua Laporan" dan daftar kedua adalah "Laporan Favorit". Di daftar pertama, jika saya mengetuk ikon bintang untuk laporan, itu memperbarui database untuk beralih ke status favorit dari laporan itu. Saya kemudian menggeser dan berhasil melihat laporan ini di UI daftar kedua. Jadi mungkin instance disimpan dalam memori tetapi dalam beberapa kasus (misalnya, milikku) konten akan benar-benar diperbarui dengan baik untuk FragmentPagerAdapter
ban-geoengineering
14

FragmentPagerAdaptermenyimpan data sebelumnya yang diambil dari adaptor sambil FragmentStatePagerAdaptermengambil nilai baru dari adaptor setiap kali dieksekusi.

vinay kumar
sumber
4

FragmentStatePagerAdapter = Untuk mengakomodasi sejumlah besar fragmen di ViewPager. Karena adaptor ini menghancurkan fragmen ketika tidak terlihat oleh pengguna dan hanya disimpanInstanceState fragmen disimpan untuk penggunaan lebih lanjut. Dengan cara ini jumlah memori yang rendah digunakan dan kinerja yang lebih baik dikirim jika fragmen dinamis.

Dwivedi Ji
sumber
1

FragmentPagerAdapter : fragmen dari setiap halaman yang dikunjungi pengguna akan disimpan dalam memori, meskipun tampilan akan dihancurkan. Jadi ketika halaman itu terlihat lagi, tampilan akan dibuat kembali tetapi contoh fragmen tidak dibuat kembali. Ini dapat menghasilkan sejumlah besar memori yang digunakan. FragmentPagerAdapter harus digunakan ketika kita perlu menyimpan seluruh fragmen dalam memori. FragmentPagerAdapter memanggil detach (Fragment) pada transaksi alih-alih menghapus (Fragment).

FragmentStatePagerAdapter : instance fragmen dihancurkan ketika tidak terlihat oleh Pengguna, kecuali keadaan fragmen yang disimpan. Ini menghasilkan hanya menggunakan sedikit Memori dan dapat berguna untuk menangani set data yang lebih besar. Seharusnya digunakan ketika kita harus menggunakan fragmen dinamis, seperti fragmen dengan widget, karena datanya dapat disimpan di AppInstanceState yang disimpan. Juga itu tidak akan mempengaruhi kinerja bahkan jika ada sejumlah besar fragmen.

foroogh.Varmazyar
sumber