(#) RecyclerView Problems
!!! ERROR: RecyclerView Problems
This is an error.
Id
: `RecyclerView`
Summary
: RecyclerView Problems
Severity
: Error
Category
: Correctness
Platform
: Android
Vendor
: Android Open Source Project
Feedback
: https://issuetracker.google.com/issues/new?component=192708
Since
: 2.0.0 (April 2016)
Affects
: Kotlin and Java files
Editing
: This check runs on the fly in the IDE editor
Implementation
: [Source Code](https://cs.android.com/android-studio/platform/tools/base/+/mirror-goog-studio-main:lint/libs/lint-checks/src/main/java/com/android/tools/lint/checks/RecyclerViewDetector.kt)
Tests
: [Source Code](https://cs.android.com/android-studio/platform/tools/base/+/mirror-goog-studio-main:lint/libs/lint-tests/src/test/java/com/android/tools/lint/checks/RecyclerViewDetectorTest.kt)
`RecyclerView` will **not** call `onBindViewHolder` again when 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.
(##) Example
Here is an example of lint warnings produced by this check:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~text
src/test/pkg/RecyclerViewTest.java:69:Error: Do not treat position as
fixed; only use immediately and call holder.getAdapterPosition() to look
it up later [RecyclerView]
public void onBindViewHolder(ViewHolder holder, int position) {
------------
src/test/pkg/RecyclerViewTest.java:82:Error: Do not treat position as
fixed; only use immediately and call holder.getAdapterPosition() to look
it up later [RecyclerView]
public void onBindViewHolder(ViewHolder holder, final int position) {
------------------
src/test/pkg/RecyclerViewTest.java:102:Error: Do not treat position as
fixed; only use immediately and call holder.getAdapterPosition() to look
it up later [RecyclerView]
public void onBindViewHolder(ViewHolder holder, final int position) {
------------------
src/test/pkg/RecyclerViewTest.java:111:Error: Do not treat position as
fixed; only use immediately and call holder.getAdapterPosition() to look
it up later [RecyclerView]
public void onBindViewHolder(ViewHolder holder, final int position, List<Object> payloads) {
------------------
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Here is the source file referenced above:
`src/test/pkg/RecyclerViewTest.java`:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~java linenumbers
package test.pkg;
import androidx.recyclerview.widget.RecyclerView;
import android.view.View;
import android.widget.TextView;
import java.util.List;
@SuppressWarnings({"ClassNameDiffersFromFileName", "unused"})
public class RecyclerViewTest {
// From https://developer.android.com/training/material/lists-cards.html
public abstract static class Test1 extends RecyclerView.Adapter {
private String[] mDataset;
public static class ViewHolder extends RecyclerView.ViewHolder {
public TextView mTextView;
public ViewHolder(TextView v) {
super(v);
mTextView = v;
}
}
public Test1(String[] myDataset) {
mDataset = myDataset;
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.mTextView.setText(mDataset[position]); // OK
}
}
public abstract static class Test2 extends RecyclerView.Adapter {
public static class ViewHolder extends RecyclerView.ViewHolder {
public ViewHolder(View v) {
super(v);
}
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
// OK
}
}
public abstract static class Test3 extends RecyclerView.Adapter {
public static class ViewHolder extends RecyclerView.ViewHolder {
public ViewHolder(View v) {
super(v);
}
}
@Override
public void onBindViewHolder(ViewHolder holder, final int position) {
// OK - final, but not referenced
}
}
public abstract static class Test4 extends RecyclerView.Adapter {
private int myCachedPosition;
public static class ViewHolder extends RecyclerView.ViewHolder {
public ViewHolder(View v) {
super(v);
}
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
myCachedPosition = position; // ERROR: escapes
}
}
public abstract static class Test5 extends RecyclerView.Adapter {
public static class ViewHolder extends RecyclerView.ViewHolder {
public ViewHolder(View v) {
super(v);
}
}
@Override
public void onBindViewHolder(ViewHolder holder, final int position) {
new Runnable() {
@Override public void run() {
System.out.println(position); // ERROR: escapes
}
}.run();
}
}
// https://code.google.com/p/android/issues/detail?id=172335
public abstract static class Test6 extends RecyclerView.Adapter {
List myData;
public static class ViewHolder extends RecyclerView.ViewHolder {
private View itemView;
public ViewHolder(View v) {
super(v);
}
}
@Override
public void onBindViewHolder(ViewHolder holder, final int position) {
holder.itemView.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
myData.get(position); // ERROR
}
});
}
@Override
public void onBindViewHolder(ViewHolder holder, final int position, List