Pertanyaan tentang siklus hidup aplikasi atau fragmen Android sangat penting untuk android yang sedang berlatih (pengembang android). Mengapa Karena urutan pelaksanaan panggilan balik dari semua metode yang terkait dengan keadaan siklus hidup ( onCreate () , onStart () , dll.) Adalah kode-keras dan aplikasi yang salah akan menyebabkan aplikasi tidak dapat dioperasikan. Apa hubungan siklus hidup dengan itu? - Habretchit yang penuh perhatian akan bertanya. Lagi pula, judulnya, sepertinya, bukan tentang dia? Saya menjawab: ada sesuatu yang sama antara siklus kehidupan kegiatan dan pekerjaan RecyclerView - ada SULIT KERAS pelaksanaan metode panggilan balik saat menggunakan widget ini, dan, oleh karena itu, kebutuhan untuk MENERAPKAN DENGAN BENAR .
Jika ini tidak dilakukan, maka daftar dapat berperilaku dengan cara yang sangat misterius.
Adaptor minimum untuk RecyclerView
Sebagai contoh. Ada adaptor daftar dengan bantalan minimum standar:
Listing 1
public class RvCustomAdapter extends RecyclerView.Adapter<RvCustomAdapter.CustomViewHolder> { private final Frag1 frag; private final LayoutInflater lInflater; private ArrayList<JSONDataSet> dataSet; ... ... ... public RvCustomAdapter(final Frag1 fragment) { this.frag = fragment; this.lInflater = (LayoutInflater) fragment.getContext() .getSystemService(Context.LAYOUT_INFLATER_SERVICE); this.dataSet = new ArrayList<>(); } ... ... ... @Override public CustomViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
Dalam kode metode onBindViewHolder () dari adaptor dari daftar kami, elemen-elemen yang berisi kotak centang (Kotak centang ), ada daya tarik untuk metode handler ( pemegang 'a), di mana data dibaca dari koleksi yang terhubung ke adaptor dan berdasarkan itu diatur - centang-kotak - status, serta elemen yang diperlukan ( Pendengar ) terhubung ke berbagai elemen antarmuka:
Listing 2
void showData(final int position) { cur = dataSet.get(position); cb_Data.setChecked(cur.isChecked()); ... ... ... cb_Data.setOnCheckedChangeListener(cb_DataOnCheckedChangeListener); ll_Data.setOnClickListener(ll_DataOnClickListener); } private OnClickListener ll_DataOnClickListener = new OnClickListener() { @Override public void onClick(View view) { cur.setChecked(!cur.isChecked()); cb_Data.setChecked(cur.isChecked()); } }; private OnCheckedChangeListener cb_DataOnCheckedChangeListener = new OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton compoundButton, boolean checked) { cur.setChecked(checked); compoundButton.setChecked(checked); setItemsColor(checked); if (checked) { if (...) { (frag).addSelectedItemsCounter(cur); } else { cur.setChecked(!checked); compoundButton.setChecked(!checked); setItemsColor(!checked); if (...) { createPrimaryDialog(); } else { createSecondaryDialog(); } } } else { (frag).remSelectedItemsCounter(cur); } } };
Ketika bendera diatur dan kondisi tertentu terpenuhi, pendengar mengubah data dalam koleksi, dan ketika tidak dieksekusi, mereka menampilkan salah satu atau kotak dialog lainnya.
Ternyata sesuatu seperti ini:



Pada Gambar-1 - daftar yang dihasilkan. Dalam Gambar-2 - Item daftar yang ditandai. Pada Gambar-3 - dialog menginformasikan tentang pelanggaran kondisi saat menandai elemen berikutnya.
Untuk mendapatkan hasilnya dengan manajer tata letak daftar Gambar-1 ( LayoutManager ), urutan pemanggilan fungsi-fungsi yang diperlukan dilakukan:
Algoritma 1
- Rv_Adapter.getItemCount () - memeriksa jumlah elemen dalam koleksi;
- Rv_Adapter.onAttachedToRecyclerView () - adaptor terhubung ke widget;
- Sementara ruang daftar tidak diisi dengan elemen daftar, langkah-langkah algoritma 2 berikut dilakukan untuk daftar:
Algoritma 2
- Rv_Adapter.onCreateViewHolder () - untuk setiap elemen koleksi, handler-nya sendiri dibuat;
- CustomViewHolder () - konstruktor handler dieksekusi;
- Rv_Adapter.onBindViewHolder () - untuk setiap contoh, pembuat tampilan dimulai;
- Rv_Adapter.onViewAttachedToWindow () - tampilan yang dihasilkan terhubung ke jendela;
Semuanya hebat! Kalau bukan karena "Tapi." Sebaliknya, TAPI!
Masalah
Saat menggulir daftar panjang yang berisi setidaknya beberapa lusin item, kami akan menerima pesan dari Gambar-3 tanpa tindakan lain.
Pemecahan masalah
Alasannya adalah bahwa ketika menulis kode adaptor, KAMI TIDAK AKAN MENERIMA PESANAN KINERJA DARI FUNGSI CALLBACK yang tercantum di sini dan di sini saat menggulir. Dan dia seperti ini:
Algoritma 3
- Ketika bersembunyi di luar negeri visibilitas setiap elemen daftar untuk instance terkait dari handler, metode Rv_Adapter.onViewDetachedFromWindow () dijalankan , yang memutuskan tampilan persembunyian dari jendela;
- Ketika setiap elemen baru dari daftar ( itemView ) muncul dari luar lingkup visibilitas, Algoritma 2 dijalankan untuk instance handler terkait;
Tapi itu belum semuanya. Dengan pengaturan "default" dari manajer markup, setiap item daftar yang terputus dari jendela tidak lama berada dalam antrian untuk akses cepat. Segera setelah ada 2 dari mereka di sana, mereka dipindahkan oleh manajer ke antrian instance yang dibuang, yang ditandai dengan memanggil metode Rv_Adapter.onViewRecycled () untuk setiap item daftar yang digunakan dan sebaliknya.
Karenanya, Algoritma 3 sebenarnya terlihat seperti ini:
Algoritma 3 '
Dari Algoritma 3 'di atas terlihat bahwa jika Anda menggulir daftar lebih dari maks, jumlah posisi tampilan di dalamnya akan dibuat lagi, di mana metode Rv_Adapter.onBindViewHolder (pemegang, visiblePos) akan digunakan, yang akan mengulangi tindakan pengguna.
Kesimpulan dan rekomendasi
Untuk menghindari operasi berulang dalam metode onBindViewHolder (holder, visiblePos) ketika menggulir daftar dengan jumlah posisi lebih besar dari maks diperlukan:
- Tambahkan elemen koleksi dengan bidang dengan tanda crowding out terkait view ke dalam antrian handler yang digunakan, misalnya, bool daur ulang ;
- Masukkan instruksi tentang cara mengatur flag ini dalam metode onViewRecycled (holder) , misalnya .... setRecycled (true) ;
- Masukkan metode onBindViewHolder (holder, visiblePos) tanda ini, misalnya if (! Handler.cur.isRecycled ()) ...;
- Masukkan instruksi metode onViewAttachedToWindow (pemegang) untuk menghapus gejala ini, misalnya .... setRecycled (false) ;
Misalnya , seperti ini:
Listing 3
@Override public void onViewRecycled(@NonNull CustomViewHolder holder) { super.onViewRecycled(holder); holder.cur.setRecycled(true); } @Override public void onBindViewHolder(@NonNull CustomViewHolder holder, int position) { if (!holder.cur.isRecycled()){ ... ... ... } } @Override public void onViewAttachedToWindow(@NonNull CustomViewHolder holder) { super.onViewAttachedToWindow(holder); holder.cur.setRecycled(false); }