I\'m using RecyclerView to display name of the items. My row contains single TextView. Item names are stored in List
Just prohibit RecyclerView's scroll when data is changing.
Like as my code:
mRecyclerView.setOnTouchListener(
new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (mIsRefreshing) {
return true;
} else {
return false;
}
}
}
);
More about: http://drakeet.me/recyclerview-bug-indexoutofboundsexception-inconsistency-detected-invalid-item-position-solution
I had same issue when I was setting new adapter instance on based on some selection criteria.
I have fixed my issue by using RecyclerView.swapAdapter(adapter, true)
When we set new adapter.
I have same issue with this problem, I'm very tired to search and resolve it. But I have found answer to resolve and exceptions have not been thrown out again.
public class MyLinearLayoutManager extends LinearLayoutManager
{
public MyLinearLayoutManager(Context context) {
super(context);
}
public MyLinearLayoutManager(Context context, int orientation, boolean reverseLayout) {
super(context, orientation, reverseLayout);
}
public MyLinearLayoutManager(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
@Override
public boolean supportsPredictiveItemAnimations() {
return false;
}
@Override
public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
//override this method and implement code as below
try {
super.onLayoutChildren(recycler, state);
} catch (Exception e) {
e.printStackTrace();
}
}
}
I hope this answer will be resolve your problem.
there is one sentence in sound code :
/**
* Used when LayoutState is constructed in a scrolling state. It should
* be set the amount of scrolling we can make without creating a new
* view. Settings this is required for efficient view recycling.
*/
int mScrollingOffset;
Avoid notifyDatasetHasChanged() and do the following:
public void setItems(ArrayList<Article> newArticles) {
//get the current items
int currentSize = articles.size();
//remove the current items
articles.clear();
//add all the new items
articles.addAll(newArticles);
//tell the recycler view that all the old items are gone
notifyItemRangeRemoved(0, currentSize);
//tell the recycler view how many new items we added
notifyItemRangeInserted(0, articles.size());
}
No problem for me. Use NotifyDataSetChanged();
public class MyFragment extends Fragment{
private MyAdapter adapter;
// Your code
public void addArticle(){
ArrayList<Article> list = new ArrayList<Article>();
//Add one article in this list
adapter.addArticleFirst(list); // or adapter.addArticleLast(list);
}
}
public class ArticleAdapterRecycler extends RecyclerView.Adapter<ArticleAdapterRecycler.ViewHolder> {
private ArrayList<Article> Articles = new ArrayList<Article>();
private Context context;
// Some functions from RecyclerView.Adapter<ArticleAdapterRecycler.ViewHolder>
// Add at the top of the list.
public void addArticleFirst(ArrayList<Article> list) {
Articles.addAll(0, list);
notifyDataSetChanged();
}
// Add at the end of the list.
public void addArticleLast(ArrayList<Article> list) {
Articles.addAll(Articles.size(), list);
notifyDataSetChanged();
}
}