RecyclerView.ViewHolder - getLayoutPosition vs getAdapterPosition

90

Sejak versi pustaka dukungan baru (22.x), getPosition()metode RecyclerView.ViewHolderkelas tidak digunakan lagi sebagai pengganti metode yang disebutkan dalam topik. Saya tidak begitu mengerti perbedaan dari membaca dokumen. Bisakah seseorang menjelaskan perbedaan dalam istilah awam?

Saya memiliki kasus penggunaan berikut - Saya memberikan adaptor saya a List, dan juga ingin dapat mengaitkan info tambahan untuk setiap item daftar. Saya memiliki pemetaan posisi-ke-ekstra, dan pemetaan tersedia untuk pemegang sehingga mereka dapat mengambil ekstra untuk posisi mereka dan melakukan banyak hal dengannya. Di pemegang, metode mana yang harus saya gunakan?

Apa yang terjadi dengan posisi pemegang ketika item daftar pada indeks 0 dan 1 bertukar tempat? Apa metode kembali?

wujek
sumber

Jawaban:

116

Ini adalah situasi yang sulit, maaf karena dokumen tidak cukup.

Saat konten adaptor berubah (dan Anda memanggil notify***()), RecyclerView meminta tata letak baru. Sejak saat itu, hingga sistem tata letak memutuskan untuk menghitung tata letak baru (<16 md), posisi tata letak dan posisi adaptor mungkin tidak cocok karena tata letak belum mencerminkan perubahan adaptor.

Dalam kasus penggunaan Anda, karena data Anda terkait dengan konten adaptor Anda (dan saya berasumsi bahwa data diubah pada saat yang sama dengan perubahan adaptor), Anda harus menggunakan adapterPosition.

Namun berhati-hatilah, jika Anda memanggil notifyDataSetChanged(), karena membuat semuanya tidak valid, RecyclerView tidak tahu bahwa posisi adaptor ViewHolder hingga tata letak berikutnya dihitung. Dalam hal ini, getAdapterPosition()akan mengembalikan RecyclerView#NO_POSITION( -1).

Tetapi katakanlah jika Anda telah menelepon notifyItemInserted(0), getAdapterPosition()dari ViewHolder yang sebelumnya pada posisi 0akan 1segera mulai kembali . Jadi selama Anda mengirimkan peristiwa pemberitahuan terperinci, Anda selalu dalam keadaan baik (kami tahu posisi adaptor meskipun tata letak baru belum dihitung).

Contoh lain, jika Anda melakukan sesuatu pada klik pengguna, jika getAdapterPosition()kembali NO_POSITION, sebaiknya abaikan klik itu karena Anda tidak tahu apa yang diklik pengguna (kecuali Anda memiliki mekanisme lain, misalnya id stabil untuk mencari item).

Edit Saat Posisi Tata Letak Bagus

Katakanlah Anda sedang menggunakan LinearLayoutManagerdan ingin mengakses ViewHolder di atas item yang saat ini diklik. Dalam hal ini, Anda harus menggunakan posisi tata letak untuk mendapatkan item di atas.

mRecyclerView.findViewHolderForLayoutPosition(myViewHolder.getLayoutPosition() - 1)

Anda harus menggunakan posisi tata letak karena cocok dengan apa yang sedang dilihat pengguna di layar.

yigit
sumber
1
Saya bermain-main sedikit dan ternyata metode getAdapterPosition () selalu mengembalikan -1 pada saya. Saya men-debugnya dan alasannya adalah kode dalam metode (final ViewParent parent = itemView.getParent (); if (! (Parent instanceof RecyclerView)) {return -1;} selalu masuk ke blok if, yaitu tampilan recycler bukan induk dari tampilan sel saya. Bagaimana bisa? Kode saya untuk membuat pemegangnya adalah: return MyViewHolder (LayoutInflater.from (viewGroup.getContext ()). inflate (R.layout.test_list_item, viewGroup, false)); (Lanjutan di komentar lain.)
wujek
Ketika saya mengubah kode untuk memanggil inflate (R.layout.test_list_item, viewGroup, true); (perhatikan kebenaran untuk 'lampirkan ke root), Android melempar: java.lang.IllegalStateException: Anak yang ditentukan sudah memiliki induk. Anda harus memanggil removeView () pada induk anak terlebih dahulu. Jadi, apa cara yang benar untuk membuat view holder dengan view yang terpasang dengan benar ke recycler view? Anehnya, meskipun getAdapterPosition () mengembalikan -1 karena induknya null, yang lainnya berfungsi dengan baik.
wujek
1
Parameter boolean di inflator tata letak adalah "addToParent". Ini harus salah karena merupakan tanggung jawab LayoutManager untuk menambahkannya. Saya pikir Anda memanggil getAdapterPosition di onBind di mana Anda sudah melewati posisinya. Secara teknis, view holder mewakili posisi tersebut setelah onBind kembali. Ngomong-ngomong, kami telah memperbarui posisi getAdapter untuk mengembalikan posisi yang valid (jika memungkinkan) meskipun dilepaskan, itu akan segera dirilis.
yigit
Anda benar, saya memanggil getAdapterPosition di onBind. Apa yang harus saya lakukan dalam kasus ini sebagai gantinya, saya memang membutuhkan posisi untuk mendapatkan beberapa informasi yang memengaruhi status beberapa pandangan. Apakah memanggil getLayoutPosition dalam kasus ini baik-baik saja?
wujek
5
Anda harus menggunakan parameter posisi yang diteruskan ke metode onBind.
yigit
2


Dalam rangka untuk berdebat perbedaan (s) dari getAdapterPosition(), getLayoutPosition(), dan juga position; kami akan melihat kasus-kasus di bawah ini:

1. positionargumen dalam onBindViewHolder()metode:

Kita dapat menggunakan positionuntuk mengikat data ke tampilan dan tidak apa-apa menggunakan positionargumen untuk melakukan ini, tetapi tidak boleh menggunakan positionargumen untuk menangani klik pengguna dan jika Anda menggunakannya, Anda akan melihat peringatan yang memberitahu Anda "tidak memperlakukan positionsebagai diperbaiki dan gunakan holder.getAdapterPosition()sebagai gantinya ".

2 getAdapterPosition().:

Metode ini selalu terdiri dari posisi adaptor yang diperbarui dari holder. Artinya setiap kali Anda mengklik suatu item, Anda bertanya kepada adaptor tentang item tersebut position. jadi Anda akan mendapatkan posisi terbaru dari item ini dalam hal logika Adapter.

3 getLayoutPosition().:

Kadang-kadang, diperlukan untuk menemukan positionsegi tata letak yang diperbarui (tata letak terakhir yang dilewatkan yang dilihat pengguna sekarang), misalnya: Jika pengguna meminta yang ketiga, positiondia dapat melihat dan Anda menggunakan swipe/ dismissuntuk item atau menerapkan animasi apa pun atau dekorasi untuk item akan lebih baik untuk digunakan getLayoutPosition()daripada getAdapterPosition(), karena Anda akan selalu yakin bahwa Anda berurusan dengan posisi item dalam hal tata letak yang terbaru.


Untuk informasi lebih lanjut tentang ini; lihat disini . . .

elyar abad
sumber