棉绒错误 "Do not treat position as fixed; only use immediately..."

Lint error "Do not treat position as fixed; only use immediately..."

我正在为开源库做贡献,但遇到此代码的 lint 错误 "Do not treat position as fixed; only use immediately and call holder.getAdapterPosition() to look it up later"

  @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);
    }
  }

我假设从概念上讲它没有太大变化,但现在对 lint 很满意。为什么?

RecyclerView.Adapter.onBindViewHolder() 的文档指出:

Note that unlike ListView, RecyclerView will not call this method again if the position of the item changes in the data set unless the item itself is invalidated or the new position cannot be determined. For this reason, you should only use the position parameter while acquiring the related data item inside this method and should not keep a copy of it. If you need the position of an item later on (e.g. in a click listener), use getAdapterPosition() which will have the updated adapter position

因此,从技术上讲,项目可能 re-arranged(如排序或四处移动)并且不需要绑定,因为项目尚未失效。这意味着如果项目显示相同的数据,则可能不会调用 onBindViewHolder(),而只是它们在列表中的 position/index 发生变化。 position 变量 received 只对 bind 函数的范围有效,并不总是指向数据集中的正确位置。这就是每次需要更新位置时必须调用函数 getAdapterPosition() 的原因。

恕我直言,mLastPosition = holder.getAdapterPosition(); 仍然可能是错误的。因为 item 可能是 re-arranged 而 mLastPosition 仍然指向旧位置。

关于为什么lint是沉默的,可能是lint的规则没有那么彻底。它只是检查是否正在复制 position 参数。