web-dev-qa-db-ja.com

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

概念的にはあまり変わらなかったと思いますが、今は糸くずは満足しています。どうして?

14
Eugen Martynov

RecyclerView.Adapter.onBindViewHolder() のドキュメントには次のように記載されています。

ListViewとは異なり、アイテム自体が無効になるか、新しい位置を特定できない場合を除いて、データセット内でアイテムの位置が変更された場合、RecyclerViewはこのメソッドを再度呼び出すことはありません。このため、このメソッド内の関連データ項目を取得するときにのみ位置パラメーターを使用し、そのコピーを保持しないでください。後で(クリックリスナーなどで)アイテムの位置が必要な場合は、アダプターの位置が更新されるgetAdapterPosition()を使用します。

そのため、技術的にはアイテムを再配置(並べ替えや移動など)することができ、アイテムはまだ無効化されていないため、バインドは必要ありません。つまり、アイテムが同じデータを表示している場合はonBindViewHolder()を呼び出せない可能性がありますが、リスト内の位置/インデックスのみが変更されます。受信したposition変数は、バインド関数のスコープにのみ当てはまり、データセット内の正しい位置を常に指しているとは限りません。そのため、位置の更新が必要になるたびに関数getAdapterPosition()を呼び出す必要があります。

私見、mLastPosition = holder.getAdapterPosition();はまだ潜在的に間違っています。アイテムが再配置される可能性があり、mLastPositionがまだ古い位置を指しているためです。

Lintが沈黙している理由については、おそらくLintのルールはそれほど完全ではありません。 positionパラメータがコピーされているかどうかをチェックしているだけです。

24
S.D.