アプリに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
使用されている
このクラッシュは、リスト(アダプターによって使用される)が更新されているときにsetViewHolder
およびonBind
メソッドが呼び出されているが、notifyDataSetChanged()
が呼び出していないことが原因である可能性があります呼ばれた。これは通常、リストの更新中にリストをスクロールするか、フリングすると発生します。
解決策:ItemPOJOの個別のリスト(tempList
)を維持し、そのリストにtopData
を追加します。次に、アダプターに使用されているリストをクリアし、tempList
を使用してアダプターのリストを設定し、notifyDataSetChanged()
を呼び出します。
これはRVのバグです。 ここでの説明 を参照してください。
ほとんどの場合、notifyDataSetChanged()
を使用すると、このクラッシュを回避できますが、アニメーションとパフォーマンスが終了します。
更新中はrecyclerviewを無効にしてみてください。
recyclerView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
return true;
}
});
次のようにコードを変更します。
public void addOnTop(ArrayList<ItemPOJO> topItemList) {
Collections.reverse(topItemList);
itemList.addAll(0, topItemList);
notifyItemRangeInserted(0, topItemList.size());
}
奇妙ですが、このようにして問題を解決しました!
これを試して:
notifyItemRangeInserted(0, topItemList.size()-1);