jimmy0251 jimmy0251 - 5 months ago 102
Android Question

How to change contents of RecyclerView while scrolling

I'm using

RecyclerView
to display name of the items. My row contains single
TextView
. Item names are stored in
List<String> mItemList
.

To change contents of
RecyclerView
, I replace Strings in
mItemList
and call
notifyDataSetChanged
() on
RecyclerViewAdapter
.

But If I try to change contents of the
mItemList
while RecyclerView is scrolling, sometimes it gives me
java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid item position 157(offset:157).state:588


This happens if size of
mItemList
is less than before. So what is the correct way to change contents of the
RecyclerView
? Is this a bug in
RecyclerView
?

Here's full stack trace of Exception:

java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid item position 157(offset:157).state:588
at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:3300)
at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:3258)
at android.support.v7.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:1803)
at android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1302)
at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1265)
at android.support.v7.widget.LinearLayoutManager.scrollBy(LinearLayoutManager.java:1093)
at android.support.v7.widget.LinearLayoutManager.scrollVerticallyBy(LinearLayoutManager.java:956)
at android.support.v7.widget.RecyclerView$ViewFlinger.run(RecyclerView.java:2715)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:725)
at android.view.Choreographer.doCallbacks(Choreographer.java:555)
at android.view.Choreographer.doFrame(Choreographer.java:524)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:711)
at android.os.Handler.handleCallback(Handler.java:615)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4921)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1027)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:794)
at dalvik.system.NativeStart.main(Native Method)


AdapterView code:

private static class FileListAdapter extends RecyclerView.Adapter<FileHolder> {
private final Context mContext;
private final SparseBooleanArray mSelectedArray;
private final List<String> mList;

FileListAdapter(Context context, List<String> list, SparseBooleanArray selectedArray) {
mList = list;
mContext = context;
mSelectedArray = selectedArray;
}


@Override
public FileHolder onCreateViewHolder(ViewGroup viewGroup, int i) {

View view = LayoutInflater.from(viewGroup.getContext()).inflate(
R.layout.file_list_item, viewGroup, false);

TextView tv = (TextView) view
.findViewById(R.id.file_name_text);
Typeface font = Typeface.createFromAsset(viewGroup.getContext().getAssets(),
viewGroup.getContext().getString(R.string.roboto_regular));
tv.setTypeface(font);

return new FileHolder(view, tv);
}

@Override
public void onBindViewHolder(FileHolder fileHolder, final int i) {

String name = mList.get(i);

// highlight view if selected
setSelected(fileHolder.itemView, mSelectedArray.get(i));

// Set text
fileHolder.mTextView.setText(name);
}

@Override
public int getItemCount() {
return mList.size();
}
}

private static class FileHolder extends RecyclerView.ViewHolder {

public final TextView mTextView;

public FileHolder(View itemView, TextView tv) {
super(itemView);
mTextView = tv;
}
}

Answer

It seems to be a bug in RecyclerView, it's reported here and here. Hopefully it will be fixed in the next release.

Comments