11

I have a RecyclerView in my app everything is working fine I am while scrolling when the last item is visible I am adding some more item to the bottom and it is working fine. Now what the problem is that I have a Handler which runs after every 5 seconds and check if there is any update in the web service and if there is any update i just load the data to the top of the RecyclerView it works fine when I have not scrolled the RecyclerView but when i scroll it and the Handler is called(as it is called after every 5 seconds) then while updating the RecyclerView on the top the app crashes.

Updating function at the top:

public void addOnTop(ArrayList<ItemPOJO> topItemList) {
    for (int i = topItemList.size() - 1; i >= 0; i--) {
        itemList.add(0, topItemList.get(i));
    }
    notifyItemRangeInserted(0, topItemList.size());
    notifyDataSetChanged();
}

This is the Error log:

java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid view holder adapter positionViewHolder{419b8760 position=5 id=-1, oldPos=-1, pLpos:-1 no parent}
        at android.support.v7.widget.RecyclerView$Recycler.validateViewHolderForOffsetPosition(RecyclerView.java:4214)
        at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:4345)
        at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:4326)
        at android.support.v7.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:1955)
        at android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1364)
        at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1327)
        at android.support.v7.widget.LinearLayoutManager.scrollBy(LinearLayoutManager.java:1155)
        at android.support.v7.widget.LinearLayoutManager.scrollVerticallyBy(LinearLayoutManager.java:1012)
        at android.support.v7.widget.RecyclerView.scrollByInternal(RecyclerView.java:1363)
        at android.support.v7.widget.RecyclerView.onTouchEvent(RecyclerView.java:2227)
        at android.view.View.dispatchTouchEvent(View.java:7190)
        at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2274)
        at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2009)
        at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2280)
        at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2023)
        at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2280)
        at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2023)
        at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2280)
        at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2023)
        at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2280)
        at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2023)
        at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2280)
        at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2023)
        at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2280)
        at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2023)
        at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2280)
        at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2023)
        at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:1931)
        at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1385)
        at android.app.Activity.dispatchTouchEvent(Activity.java:2396)
        at android.support.v7.internal.view.WindowCallbackWrapper.dispatchTouchEvent(WindowCallbackWrapper.java:59)
        at android.support.v7.internal.view.WindowCallbackWrapper.dispatchTouchEvent(WindowCallbackWrapper.java:59)
        at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:1879)
        at android.view.View.dispatchPointerEvent(View.java:7370)
        at android.view.ViewRootImpl.deliverPointerEvent(ViewRootImpl.java:3182)
        at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:3127)
        at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:4164)
        at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:4143)
        at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:4235)
        at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:171)
        at android.view.InputEventReceiver.nativeConsumeBatchedInputEvents(Native Method)
        at android.view.InputEventReceiver.consumeBatchedInputEvents(InputEventReceiver.java:163)
        at android.view.ViewRootImpl.doConsumeBatchedInput(ViewRootImpl.java:4214)
        at android.view.ViewRootImpl$ConsumeBatchedInputRunnable.run(ViewRootImpl.java:4254)
        at android.view.Choreographer$CallbackRecord.run(Choreographer.java:725)
        at android.view.Choreographer.doCallbacks(Choreographer.java:555)
        at android.view.Choreographer.doFrame(Choreographer.java:523)
        at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreog

P.S.: com.android.support:recyclerview-v7:22.2.1 is used

Vishwajit Palankar
  • 3,033
  • 3
  • 28
  • 48
  • 1
    Just remove `notifyItemRangeInserted(0, topItemList.size());` since your `notifyDataSetChanged();` covers the notifications and see if that fixes the issue. – kha Jul 24 '15 at 06:53

5 Answers5

6

This crash might be caused by the fact that the setViewHolder and onBind methods are being called while your list(used by the adapter) is being updated, but notifyDataSetChanged() hasn't been called. This usually happens if you scroll through the list, or fling, while the list is being updated.

Solution: Maintain a separate list(tempList) of ItemPOJOs and append the topData in that list. Then clear the list used for the adapter, set the list of the adapter with the tempList, and call notifyDataSetChanged().

Vasily Kabunov
  • 6,511
  • 13
  • 49
  • 53
Sid
  • 1,270
  • 2
  • 15
  • 30
4

It is a bug of RV, see the discussion here.
In most cases, use notifyDataSetChanged() will avoid this crash, but it will kill Animation and Performance.

Piasy
  • 989
  • 13
  • 35
1

Change your code like this:

public void addOnTop(ArrayList<ItemPOJO> topItemList) {
    Collections.reverse(topItemList);
    itemList.addAll(0, topItemList);
    notifyItemRangeInserted(0, topItemList.size());
}

it's weird but in this way I resolved my problem!

MaryPeak
  • 149
  • 5
1

Try disabling recyclerview while refreshing:

recyclerView.setOnTouchListener(new View.OnTouchListener() {
      @Override
      public boolean onTouch(View v, MotionEvent event) {
          return true;
      }
  });
Rishabh Srivastava
  • 3,683
  • 2
  • 30
  • 58
0

Try this:

 notifyItemRangeInserted(0, topItemList.size()-1);
rassar
  • 5,412
  • 3
  • 25
  • 41
damn
  • 1