Подтвердить что ты не робот

Ошибка Lint "Не обрабатывайте позицию как фиксированную, используйте только сразу..."

Я вношу вклад в библиотеку с открытым исходным кодом и получил ошибку lint . Не обрабатывайте позицию как фиксированную, используйте ее немедленно и вызывайте holder.getAdapterPosition(), чтобы просмотреть ее позже для этого кода:

  @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
    mAdapter.onBindViewHolder(holder, position);

    if (!isFirstOnly || position > mLastPosition) {
      for (Animator anim : getAnimators(holder.itemView)) {
        anim.setDuration(mDuration).start();
        anim.setInterpolator(mInterpolator);
      }
      mLastPosition = position;
    } else {
      ViewHelper.clear(holder.itemView);
    }
  }

Я проверил, что это потому, что позиция сохраняется для будущего использования. Для создателя библиотеки возникает вопрос, зачем нужна эта логика. Но проблема исчезла, когда я изменил использование позиции на использование holder.getAdapterPosition():

  @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
    mAdapter.onBindViewHolder(holder, position);

    if (!isFirstOnly || holder.getAdapterPosition() > mLastPosition) {
      for (Animator anim : getAnimators(holder.itemView)) {
        anim.setDuration(mDuration).start();
        anim.setInterpolator(mInterpolator);
      }
      mLastPosition = holder.getAdapterPosition();
    } else {
      ViewHelper.clear(holder.itemView);
    }
  }

Я предполагаю, что концептуально это не сильно изменилось, но линт теперь удовлетворен. Зачем?

4b9b3361

Ответ 1

Документация RecyclerView.Adapter.onBindViewHolder() утверждает:

Обратите внимание, что в отличие от ListView, RecyclerView не будет вызывать этот метод снова, если позиция элемента изменяется в наборе данных, если только сам элемент недействителен или новая позиция не может быть определена. По этой причине вам следует использовать только параметр позиции, пока получение соответствующего элемента данных внутри этого метода и не должно его копию. Если вам понадобится позиция элемента позже (например, в нажмите кнопку прослушивателя), используйте getAdapterPosition(), который будет обновлен положение адаптера

Таким образом, технически элементы могут быть переупорядочены, и привязка не понадобится, поскольку элементы еще не признаны недействительными. Полученная переменная position имеет значение true только для области функции привязки и не всегда указывает на правильное положение в наборе данных. Вот почему нужна функция getAdapterPosition(), которая должна обновляться по мере необходимости.

IMHO, mLastPosition = holder.getAdapterPosition(); по-прежнему потенциально ошибочно. Поскольку элемент может быть перенастроен, а mLastPosition все еще указывает на старую позицию.

О том, почему линт молчат, возможно, правило Линта не настолько тщательное. Его только проверка того, скопирован ли параметр position или нет.