11

我的应用程序中有一个RecyclerView一切工作正常当最后一个项目可见时滚动时我正在向底部添加更多项目并且它工作正常。现在问题是我有一个Handler每 5 秒运行一次并检查 Web 服务中是否有任何更新,如果有任何更新,我只需将数据加载到顶部,RecyclerView当我没有滚动时它工作正常但是RecyclerView当我滚动它并Handler调用它时(因为它每 5 秒后调用一次),然后在更新RecyclerView顶部的应用程序时崩溃。

顶部更新功能:

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();
}

这是错误日志:

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

PS:com.android.support:recyclerview-v7:22.2.1被使用

4

5 回答 5

6

此崩溃可能是由于在更新列表(由适配器使用)时调用了setViewHolderand方法,但尚未调用。如果您在更新列表时滚动或翻动列表,通常会发生这种情况。onBindnotifyDataSetChanged()

解决方案:维护一个单独tempList的 ItemPOJO 列表()并将其附加到topData该列表中。然后清除用于适配器的列表,用 设置适配器列表tempList,然后调用notifyDataSetChanged()

于 2016-01-12T12:03:01.100 回答
4

这是 RV 的错误,请参阅此处的讨论
在大多数情况下,使用notifyDataSetChanged()会避免这种崩溃,但它会杀死动画和性能。

于 2015-08-22T04:43:59.430 回答
1

像这样更改您的代码:

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

这很奇怪,但通过这种方式我解决了我的问题!

于 2016-01-03T13:16:46.320 回答
1

刷新时尝试禁用recyclerview:

recyclerView.setOnTouchListener(new View.OnTouchListener() {
      @Override
      public boolean onTouch(View v, MotionEvent event) {
          return true;
      }
  });
于 2016-10-16T06:04:43.330 回答
0

尝试这个:

 notifyItemRangeInserted(0, topItemList.size()-1);
于 2015-08-20T02:37:02.923 回答