web-dev-qa-db-ja.com

上で更新するとRecyclerViewがクラッシュする

アプリにRecyclerViewがあります。すべてが正常に機能しています。最後のアイテムが表示されているときにスクロールしているときに、下部にさらにアイテムを追加すると、正常に機能します。 5秒ごとに実行されるHandlerがある問題は何ですか?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 使用されている

10

このクラッシュは、リスト(アダプターによって使用される)が更新されているときにsetViewHolderおよびonBindメソッドが呼び出されているが、notifyDataSetChanged()が呼び出していないことが原因である可能性があります呼ばれた。これは通常、リストの更新中にリストをスクロールするか、フリングすると発生します。

解決策:ItemPOJOの個別のリスト(tempList)を維持し、そのリストにtopDataを追加します。次に、アダプターに使用されているリストをクリアし、tempListを使用してアダプターのリストを設定し、notifyDataSetChanged()を呼び出します。

6
Sid

これはRVのバグです。 ここでの説明 を参照してください。
ほとんどの場合、notifyDataSetChanged()を使用すると、このクラッシュを回避できますが、アニメーションとパフォーマンスが終了します。

4
Piasy

更新中はrecyclerviewを無効にしてみてください。

recyclerView.setOnTouchListener(new View.OnTouchListener() {
      @Override
      public boolean onTouch(View v, MotionEvent event) {
          return true;
      }
  });
1

次のようにコードを変更します。

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

奇妙ですが、このようにして問題を解決しました!

1
MaryPeak

これを試して:

 notifyItemRangeInserted(0, topItemList.size()-1);
0
damn