Saya tidak dapat memperbarui konten di ViewPager.
Apakah penggunaan metode yang benar instantiateItem () dan getItem () di kelas FragmentPagerAdapter?
Saya hanya menggunakan getItem () untuk membuat instance dan mengembalikan fragmen saya:
@Override
public Fragment getItem(int position) {
return new MyFragment(context, paramters);
}
Ini bekerja dengan baik. Kecuali saya tidak bisa mengubah konten.
Jadi saya menemukan ini: ViewPager PagerAdapter tidak memperbarui View
"Pendekatan saya adalah menggunakan metode setTag () untuk tampilan instantiated apa pun dalam metode instantiateItem ()"
Sekarang saya ingin mengimplementasikan instantiateItem () untuk melakukan itu. Tetapi saya tidak tahu apa yang harus saya kembalikan (tipenya adalah Object) dan apa hubungannya dengan getItem (posisi int)?
Saya membaca referensi :
public abstrak Fragmen getItem (posisi int)
Kembalikan Fragmen yang terkait dengan posisi yang ditentukan.
InstantiateItem objek publik (wadah ViewGroup, posisi int)
Buat halaman untuk posisi yang diberikan. Adaptor bertanggung jawab untuk menambahkan tampilan ke wadah yang diberikan di sini, meskipun itu hanya harus memastikan ini dilakukan pada saat ia kembali dari finishUpdate (ViewGroup). Parameter
container Tampilan yang berisi halaman yang akan ditampilkan. posisi Posisi halaman yang akan dipakai.
Kembali
Mengembalikan Objek yang mewakili halaman baru. Ini tidak perlu menjadi Tampilan, tetapi bisa berupa wadah halaman lainnya.
tapi saya masih belum mengerti.
Ini kode saya. Saya menggunakan paket dukungan v4.
ViewPagerTest
public class ViewPagerTest extends FragmentActivity {
private ViewPager pager;
private MyFragmentAdapter adapter;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.pager1);
pager = (ViewPager)findViewById(R.id.slider);
String[] data = {"page1", "page2", "page3", "page4", "page5", "page6"};
adapter = new MyFragmentAdapter(getSupportFragmentManager(), 6, this, data);
pager.setAdapter(adapter);
((Button)findViewById(R.id.button)).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
reload();
}
});
}
private void reload() {
String[] data = {"changed1", "changed2", "changed3", "changed4", "changed5", "changed6"};
//adapter = new MyFragmentAdapter(getSupportFragmentManager(), 6, this, data);
adapter.setData(data);
adapter.notifyDataSetChanged();
pager.invalidate();
//pager.setCurrentItem(0);
}
}
MyFragmentAdapter
class MyFragmentAdapter extends FragmentPagerAdapter {
private int slideCount;
private Context context;
private String[] data;
public MyFragmentAdapter(FragmentManager fm, int slideCount, Context context, String[] data) {
super(fm);
this.slideCount = slideCount;
this.context = context;
this.data = data;
}
@Override
public Fragment getItem(int position) {
return new MyFragment(data[position], context);
}
@Override
public int getCount() {
return slideCount;
}
public void setData(String[] data) {
this.data = data;
}
@Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
}
MyFragment
public final class MyFragment extends Fragment {
private String text;
public MyFragment(String text, Context context) {
this.text = text;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.slide, null);
((TextView)view.findViewById(R.id.text)).setText(text);
return view;
}
}
Di sini ada juga seseorang dengan masalah yang sama, tidak ada jawaban http://www.mail-archive.com/[email protected]/msg200477.html
Jawaban:
Saat menggunakan FragmentPagerAdapter atau FragmentStatePagerAdapter, yang terbaik adalah berurusan dengan
getItem()
dan tidak menyentuhinstantiateItem()
sama sekali. TheinstantiateItem()
-destroyItem()
-isViewFromObject()
antarmuka pada PagerAdapter adalah antarmuka tingkat rendah yang FragmentPagerAdapter penggunaan untuk melaksanakan lebih sederhanagetItem()
antarmuka.Sebelum membahas hal ini, saya harus mengklarifikasi hal itu
Versi sebelumnya dari jawaban ini membuat kesalahan dengan menggunakan FragmentPagerAdapter sebagai contohnya - itu tidak akan berfungsi karena FragmentPagerAdapter tidak pernah menghancurkan sebuah fragmen setelah itu ditampilkan pertama kali.
Saya tidak merekomendasikan
setTag()
danfindViewWithTag()
solusi yang disediakan di pos yang Anda tautkan. Seperti yang telah Anda temukan, gunakansetTag()
danfindViewWithTag()
tidak bekerja dengan fragmen, jadi itu bukan pasangan yang baik.Solusi yang tepat adalah menimpanya
getItemPosition()
. SaatnotifyDataSetChanged()
dipanggil, ViewPager memanggilgetItemPosition()
semua item dalam adaptornya untuk melihat apakah item tersebut perlu dipindahkan ke posisi yang berbeda atau dihapus.Secara default,
getItemPosition()
mengembalikanPOSITION_UNCHANGED
, yang berarti, "Objek ini baik-baik saja, jangan dihancurkan atau dihapus." KembaliPOSITION_NONE
memperbaiki masalah dengan mengatakan, "Objek ini bukan lagi item yang saya tampilkan, hapus saja." Jadi itu memiliki efek menghapus dan menciptakan kembali setiap item dalam adaptor Anda.Ini adalah perbaikan yang sepenuhnya sah! Perbaikan ini membuat notifyDataSetChanged berperilaku seperti Adaptor biasa tanpa melihat daur ulang. Jika Anda menerapkan perbaikan ini dan kinerjanya memuaskan, Anda siap. Pekerjaan selesai.
Jika Anda membutuhkan kinerja yang lebih baik, Anda dapat menggunakan
getItemPosition()
implementasi yang lebih menarik . Berikut ini contoh pager yang membuat fragmen dari daftar string:Dengan implementasi ini, hanya fragmen yang menampilkan judul baru yang akan ditampilkan. Setiap fragmen yang menampilkan judul yang masih ada dalam daftar akan dipindahkan ke posisi baru mereka dalam daftar, dan fragmen dengan judul yang tidak lagi ada dalam daftar sama sekali akan dihancurkan.
Bagaimana jika fragmen belum dibuat ulang, tetapi tetap perlu diperbarui? Pembaruan untuk fragmen hidup paling baik ditangani oleh fragmen itu sendiri. Bagaimanapun, itulah keuntungan memiliki sebuah fragmen - itu adalah pengontrolnya sendiri. Sebuah fragmen dapat menambahkan pendengar atau pengamat ke objek lain
onCreate()
, dan kemudian menghapusnyaonDestroy()
, sehingga mengelola pembaruan itu sendiri. Anda tidak harus memasukkan semua kode pembaruan ke dalamnyagetItem()
seperti yang Anda lakukan pada adaptor untuk ListView atau tipe AdapterView lainnya.Satu hal terakhir - hanya karena FragmentPagerAdapter tidak menghancurkan sebuah fragmen tidak berarti bahwa getItemPosition sama sekali tidak berguna dalam FragmentPagerAdapter. Anda masih dapat menggunakan panggilan balik ini untuk menyusun ulang fragmen Anda di ViewPager. Itu tidak akan pernah menghapus mereka sepenuhnya dari FragmentManager.
sumber
FragmentStatePagerAdapter
, saya dapat melihatnya menghapus fragmen saya dan membuat instance baru. Tetapi instance baru menerima BundelInstanceState yang disimpan dengan keadaan fragmen lama. Bagaimana saya bisa sepenuhnya menghancurkan fragmen sehingga Bundle menjadi nol ketika dibuat lagi?Alih-alih kembali
POSITION_NONE
darigetItemPosition()
dan menyebabkan rekreasi tampilan penuh, lakukan ini:Fragmen Anda harus mengimplementasikan
UpdateableFragment
antarmuka:dan antarmuka:
Kelas data Anda:
sumber
Fragment
secara dinamis, lihat: stackoverflow.com/questions/19891828/…d page on refreshes the 1-st page only after swiping pages? thw 2
selalu kosong. terima kasihbagi mereka yang masih menghadapi masalah yang sama yang saya hadapi sebelumnya ketika saya memiliki
ViewPager
7 fragmen. default untuk fragmen ini untuk memuat konten bahasa Inggris dariAPI
layanan tetapi masalah di sini bahwa saya ingin mengubah bahasa dari aktivitas pengaturan dan setelah menyelesaikan kegiatan pengaturan saya inginViewPager
dalam kegiatan utama untuk menyegarkan fragmen agar sesuai dengan pilihan bahasa dari pengguna dan memuat konten Arab jika pengguna memilih bahasa Arab di sini apa yang saya lakukan untuk bekerja sejak pertama kali1- Anda harus menggunakan FragmentStatePagerAdapter seperti yang disebutkan di atas.
2- pada mainActivity saya menimpa onResume dan melakukan hal berikut
3-i
getItemPosition()
meng -override di mPagerAdapter dan membuatnya kembaliPOSITION_NONE
.bekerja seperti pesona
sumber
Saya telah menemui masalah ini dan akhirnya menyelesaikannya hari ini, jadi saya menuliskan apa yang telah saya pelajari dan saya harap ini membantu bagi seseorang yang baru mengenal Android
ViewPager
dan memperbarui seperti yang saya lakukan. Saya menggunakanFragmentStatePagerAdapter
API level 17 dan saat ini hanya memiliki 2 fragmen. Saya pikir pasti ada sesuatu yang tidak benar, tolong perbaiki saya, terima kasih.Data berseri harus dimuat ke dalam memori. Ini bisa dilakukan menggunakan
CursorLoader
/AsyncTask
/Thread
. Apakah itu dimuat secara otomatis tergantung pada kode Anda. Jika Anda menggunakanCursorLoader
, ini dimuat secara otomatis karena ada pengamat data terdaftar.Setelah Anda menelepon
viewpager.setAdapter(pageradapter)
, adaptorgetCount()
terus dipanggil untuk membuat fragmen. Jadi jika data sedang dimuat,getCount()
dapat mengembalikan 0, sehingga Anda tidak perlu membuat fragmen dummy karena tidak ada data yang ditampilkan.Setelah data dimuat, adaptor tidak akan membuat fragmen secara otomatis karena
getCount()
masih 0, sehingga kita dapat mengatur nomor data yang sebenarnya dimuat untuk dikembalikan olehgetCount()
, lalu memanggil adaptornotifyDataSetChanged()
.ViewPager
mulai membuat fragmen (hanya 2 fragmen pertama) dengan data dalam memori. Itu dilakukan sebelumnotifyDataSetChanged()
dikembalikan. MakaViewPager
memiliki fragmen yang tepat yang Anda butuhkan.Jika data dalam database dan memori diperbarui (tulis melalui), atau hanya data dalam memori yang diperbarui (tulis kembali), atau hanya data dalam database yang diperbarui. Dalam dua kasus terakhir jika data tidak secara otomatis dimuat dari database ke memori (seperti yang disebutkan di atas). The
ViewPager
dan adaptor pager hanya berurusan dengan data dalam memori.Jadi ketika data dalam memori diperbarui, kita hanya perlu memanggil adaptor
notifyDataSetChanged()
. Karena fragmen sudah dibuat, adaptoronItemPosition()
akan dipanggil sebelumnotifyDataSetChanged()
kembali. Tidak ada yang perlu dilakukan digetItemPosition()
. Kemudian data diperbarui.sumber
notifyDataSetChanged()
saja kemudian baru saja diperbarui secara otomatis, karena fragmen (dengan chartview) yang saya gunakan akan menyegarkan sendiri. jika tidak, seperti fragmen statis, saya harus menelepononItemPositon()
dan mengembalikanPOSITION_NONE
maaf tentang hal ituCoba
destroyDrawingCache()
di ViewPager setelahnotifyDataSetChanged()
di kode Anda.sumber
Fragments
pager tampilan saya. Jadi terima kasihSetelah berjam-jam frustrasi ketika mencoba semua solusi di atas untuk mengatasi masalah ini dan juga mencoba banyak solusi pada pertanyaan serupa lainnya seperti ini , ini dan ini yang semuanya GAGAL dengan saya untuk menyelesaikan masalah ini dan membuat
ViewPager
untuk menghancurkan yang lamaFragment
dan mengisipager
dengan yang baruFragment
. Saya telah memecahkan masalah sebagai berikut:1) Buat
ViewPager
kelas untuk diperluasFragmentPagerAdapter
sebagai berikut:2) Buat Item untuk
ViewPager
toko itutitle
danfragment
sebagai berikut:3) Buat konstruktor dari
ViewPager
take myFragmentManager
instance untuk menyimpannya diclass
sebagai berikut:4) Buat metode untuk mengatur ulang
adapter
data dengan data baru dengan menghapus semua sebelumnyafragment
darifragmentManager
itu sendiri secara langsung untuk membuatadapter
untuk mengatur yang barufragment
dari daftar baru lagi sebagai berikut:5) Dari wadah
Activity
atauFragment
jangan inisialisasi ulang adaptor dengan data baru. Atur data baru melalui metodesetPagerItems
dengan data baru sebagai berikut:Saya harap ini membantu.
sumber
Untuk beberapa alasan tidak ada jawaban yang bekerja untuk saya, jadi saya harus mengganti metode restoreState tanpa memanggil super di fragmentStatePagerAdapter. Kode:
sumber
Saya sedikit memodifikasi solusi yang disediakan oleh Bill Phillips agar sesuai dengan kebutuhan saya
sehingga
getItemPosition()
kembaliPOSITION_NONE
hanya untuk orang-fragmen yang saat ini diFragmentManager
saatgetItemPosition
disebut. (Perhatikan bahwa iniFragmentStatePager
dan yangViewPager
terkait dengannya terkandung dalam Fragmen bukan dalam Aktivitas)sumber
Saya memiliki masalah yang sama tetapi tidak ingin mempercayai solusi yang ada (nama tag berkode keras dll.) Dan saya tidak bisa membuat solusi M-WaJeEh bekerja untuk saya. Ini solusinya:
Saya menyimpan referensi untuk fragmen yang dibuat di getItem dalam sebuah array. Ini berfungsi dengan baik selama aktivitas tidak dihancurkan karena perubahan konfigurasi atau kurangnya memori atau apa pun (-> ketika kembali ke aktivitas, fragmen kembali ke keadaan terakhir mereka tanpa 'getItem' dipanggil lagi dan dengan demikian tanpa memperbarui array ).
Untuk menghindari masalah ini, saya menerapkan instantiateItem (ViewGroup, int) dan memperbarui array saya di sana, seperti ini:
Jadi, di satu sisi saya senang bahwa saya menemukan solusi yang berfungsi untuk saya dan ingin membaginya dengan Anda, tetapi saya juga ingin bertanya apakah ada orang lain yang mencoba sesuatu yang serupa dan apakah ada alasan mengapa saya tidak boleh lakukan seperti itu Sejauh ini bekerja sangat baik untuk saya ...
sumber
myFragments
dalampublic void destroyItem(ViewGroup container, int position, Object object)
juga sehingga Anda tidak mengambil referensi frmentasi basi.Saya menggunakan perpustakaan EventBus untuk memperbarui
Fragment
konten diViewPager
. Logikanya sederhana, seperti halnya dokumen EventBus gimana caranya . Tidak perlu dikendalikanFragmentPagerAdapter
instance. Kode di sini:1: Tentukan acara
Tentukan pesan mana yang perlu diperbarui.
2. Persiapkan pelanggan
Tulis kode di bawah ini dalam Fragmen yang perlu diperbarui.
3.Post acara
Tulis kode di bawah ini di lain
Activity
atau yang lainFragment
yang perlu memperbarui parametersumber
Jika Anda ingin menggunakan FragmentStatePagerAdapter, silakan lihat di https://code.google.com/p/android/issues/detail?can=2&start=0&num=100&q=&colspec=ID%20Type%20Status%20Owner%20Summary%% 20Stars & groupby = & sort = & id = 37990 . Ada masalah dengan FragmentStatePagerAdapter yang mungkin atau mungkin tidak mengganggu kasus penggunaan Anda.
Juga, tautan juga memiliki beberapa solusi. Beberapa mungkin sesuai dengan kebutuhan Anda.
sumber
Saya telah mengalami masalah yang sama dan saya telah mencari terlalu banyak. Setiap jawaban yang diberikan di stackoverflow atau melalui google bukanlah solusi untuk masalah saya. Masalah saya mudah. Saya punya daftar, saya tampilkan daftar ini dengan viewpager. Ketika saya menambahkan elemen baru ke kepala daftar dan saya menyegarkan tak berguna viewpager berubah. Solusi terakhir saya sangat mudah digunakan siapa saja. Ketika elemen baru ditambahkan ke daftar dan ingin menyegarkan daftar. Pertama-tama atur adaptor viewpager ke nol, kemudian buat kembali adaptor dan atur i untuk itu ke viewpager.
Pastikan adaptor Anda harus memperpanjang FragmentStatePagerAdapter
sumber
Berikut ini adalah implementasi saya yang menggabungkan info dari @Bill Phillips One mendapat caching fragmen sebagian besar waktu, kecuali ketika data telah berubah. Sederhana, dan sepertinya berfungsi dengan baik.
MyFragmentStatePagerAdapter.java
MyActivity.java
sumber
Saya telah mencoba banyak pendekatan berbeda, tidak ada yang benar-benar menyelesaikan masalah saya. Di bawah ini adalah bagaimana saya menyelesaikannya dengan campuran solusi yang disediakan oleh Anda semua. Terimakasih semuanya.
Saya hanya ingin me-refresh halaman 0 setelah onResume ().
Di FragmentsMain saya, ada "halaman" bilangan bulat publik, yang dapat memberi tahu saya apakah itu halaman yang ingin saya segarkan.
sumber
Saya tahu saya terlambat untuk pesta. Saya telah memperbaiki masalah dengan menelepon
TabLayout#setupWithViewPager(myViewPager);
setelahnyaFragmentPagerAdapter#notifyDataSetChanged();
sumber
Solusi ini tidak akan bekerja untuk semua orang, tetapi dalam kasus saya, setiap Fragmen dalam ViewPager saya adalah kelas yang berbeda, dan hanya satu dari mereka yang pernah ada pada suatu waktu.
Dengan batasan ini, solusi ini aman dan harus aman digunakan dalam produksi.
Jika Anda memiliki beberapa versi dari fragmen yang sama, Anda dapat menggunakan strategi yang sama ini untuk memanggil metode pada fragmen tersebut untuk menentukan apakah itu fragmen yang ingin Anda perbarui.
sumber
Ini mungkin bisa membantu seseorang - dalam kasus saya saat memasukkan halaman baru, pager tampilan meminta posisi fragmen yang ada dua kali, tetapi tidak menanyakan posisi item baru, menyebabkan perilaku yang salah dan data tidak ditampilkan.
Salin sumber untuk untuk FragmentStatePagerAdapter (tampaknya belum diperbarui dalam usia).
Ganti notifyDataSetChanged ()
Tambahkan cek kewarasan untuk destroyItem () untuk mencegah crash:
sumber
Saya telah memeriksa semua jawaban di atas dan sejumlah posting lainnya tetapi masih tidak dapat menemukan sesuatu yang bekerja untuk saya (dengan berbagai jenis fragmen bersamaan dengan menambahkan dan menghapus tab secara dinamis). FWIW mengikuti pendekatan adalah apa yang berhasil untuk saya (kalau-kalau ada orang lain yang memiliki masalah yang sama).
sumber
Gunakan FragmentStatePagerAdapter alih-alih FragmentPagerAdapter jika Anda ingin membuat ulang atau memuat ulang fragmen berdasarkan indeks Misalnya, jika Anda ingin memuat ulang fragmen selain FirstFragment, Anda dapat memeriksa instance dan mengembalikan posisi seperti ini
sumber
Anda perlu mengubah elemen mFragments instantiateItem getItemPosition.
Berbasis AndroidX FragmentStatePagerAdapter.java, karena
mFragments
posisi elemen tidak berubah ketika memanggil notifyDataSetChanged ().Sumber: https://github.com/cuichanghao/infivt/blob/master/library/src/main/java/cc/cuichanghao/library/FragmentStatePagerChangeableAdapter.java
Contoh: https://github.com/cuichanghao/infivt/blob/master/app/src/main/java/cc/cuichanghao/infivt/MainActivityChangeablePager.kt
Anda dapat menjalankan proyek ini untuk mengonfirmasi cara kerjanya. https://github.com/cuichanghao/infivt
sumber