RecyclerView.ViewHolder - getLayoutPosition vs getAdapterPosition

Поскольку новая версия библиотеки поддержки (22.x) метод getPosition() класса RecyclerView.ViewHolder устарел вместо методов, упомянутых в теме. Я действительно не понимаю, как читать документы. Может ли кто-нибудь объяснить разницу в условиях неспециалиста, пожалуйста?

У меня есть следующий прецедент - я даю моему адаптеру список, а также хочу, чтобы у вас была возможность связать дополнительную информацию для каждого элемента списка. У меня есть сопоставление позиции для дополнительного, и отображение доступно для держателей, чтобы они могли получить дополнительные для своей позиции и делать с ним вещи. В держателе, какой метод я должен использовать?

Что происходит с позициями держателя, когда элементы списка с индексами 0 и 1 являются переключаемыми местами? Что возвращают методы?

Ответ 1

Это сложная ситуация, извините, что документов недостаточно.

Когда изменяется содержимое адаптера (и вы вызываете notify***()), RecyclerView запрашивает новый макет. С этого момента, пока система макета не решит рассчитать новый макет (< 16 мс), расположение макета и позиция адаптера могут не совпадать, поскольку макет еще не изменил изменения адаптера.

В вашем случае использования, так как ваши данные связаны с содержимым вашего адаптера (и я предполагаю, что данные будут изменены одновременно с изменениями адаптера), вы должны использовать adapterPosition.

Будьте осторожны, если вы вызываете notifyDataSetChanged(), потому что он делает недействительным все, RecyclerView не знает, что позиция адаптера ViewHolder до вычисления следующего макета. В этом случае getAdapterPosition() вернет RecyclerView#NO_POSITION (-1).

Но скажем, если вы вызвали notifyItemInserted(0), getAdapterPosition() из ViewHolder, который ранее находился в позиции 0, немедленно вернул 1. Таким образом, пока вы отправляете подробные уведомления о событиях, вы всегда в хорошем состоянии (мы знаем положение адаптера, даже если новый макет еще не рассчитан).

Другой пример: если вы делаете что-то на клике пользователя, если getAdapterPosition() возвращает NO_POSITION, лучше игнорировать этот клик, потому что вы не знаете, какой пользователь нажал (если у вас нет другого механизма, например, стабильного ids для поиска элемента).

Изменить, когда позиция макета хорошая

Предположим, вы используете LinearLayoutManager и хотите получить доступ к ViewHolder над текущим кликом. В этом случае вы должны использовать расположение макета, чтобы получить элемент выше.

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

Вы должны использовать расположение макета, так как оно соответствует тому, что пользователь видит на экране.