I\'m using RecyclerView
to display name of the items. My row contains single TextView
. Item names are stored in List
I figure out that, for me this exception comes when two things happens at the same time i.e.
1) Scrolling of recyclerview
2) data set getting changed
So, I solved this problem by disabling the scroll till the notifydatasetchanged is called.
leaderAdapter.notifyDataSetChanged();
pDialog.hide();
To disable the scroll, I have used a progress dialog, whose setCancelable is false.
pDialog = new ProgressDialog(getActivity());
pDialog.setMessage("Please wait...");
pDialog.setCancelable(false);
The trick here is to enable the scrolling only when the data set has been updated.
I got this to work using Cocorico suggestion in a previous answer (https://stackoverflow.com/a/26927186/3660638) but there's a catch: since I'm using a SortedList
, using notifyDataSetChanged() everytime there's a change in data (add, remove, etc) makes you lose the item animations that you get with notifyItemXXXXX(position)
, so what I ended up doing was using it only when I change the data in batch, like:
public void addAll(SortedList<Entity> items) {
movieList.beginBatchedUpdates();
for (int i = 0; i < items.size(); i++) {
movieList.add(items.get(i));
}
movieList.endBatchedUpdates();
notifyDataSetChanged();
}
I dont see anthing wrong with the code you posted. The only thing weird to me is this line
setSelected(fileHolder.itemView, mSelectedArray.get(i));
in your onBindViewHolder method in the adapter.. are you updating this array too when you change the size of your list of items in the array?
I had similar problem while i try to add first item into recyclerView with notifyItemInserted method, so i modified addItem function on my adapter as below and it resolved.
Weird problem, hope that it'll be fixed soon thoug!
public void addItem(int position, TableItem item) {
boolean firstEntry = false;
if (items.size() == 0) {
firstEntry = true;
}
items.add(position, item);
if (firstEntry) {
notifyDataSetChanged();
} else {
notifyItemInserted(position);
}
}
Although a couple of useful hyperlinks about this issue are given in the accepted answer, it is not true that this behavior of RecyclerView
while scrolling is a bug.
If you see this exception, most probably you forget to notify the adapter after the content of RecyclerView
is "changed". People call notifyDataSetChanged()
only after an item is added to the data set. However, the inconsistency occurs not only after you refill the adapter, but also when you remove an item or you clear the data set, you should refresh the view by notifying the adapter about this change:
public void refillAdapter(Item item) {
adapter.add(item);
notifyDataSetChanged();
}
public void cleanUpAdapter() {
adapter.clear();
notifyDataSetChanged(); /* Important */
}
In my case, I tried to clean up the adapter in onStop()
, and refill it in onStart()
. I forgot to call notifyDataSetChanged()
after the adapter is cleaned by using clear()
. Then, whenever I changed the state from onStop()
to onStart()
and swiftly scrolled the RecyclerView
while the data set is reloading, I saw this exception. If I waited the end of reloading without scrolling, there would be no exception since the adapter can be reinstated smoothly this time.
In short, the RecyclerView
is not consistent when it is on view change. If you try to scroll the view while the changes in the data set are processed, you see java.lang.IndexOutOfBoundsException: Inconsistency detected
. To eliminate this problem, you should notify the adapter immediately after the data set is changed.
This problem is coming to recyclerview if you use
adapter.setHasStableIds(true);
if you set so, remove this, and to update your dataset inside adaptor;
if you still face the issue, invalidate all views once you get new data and then update your dataset.