rubensousa / DpadRecyclerView

A RecyclerView built for Android TV with Compose in mind and as a replacement for Leanback's BaseGridView.
https://rubensousa.github.io/DpadRecyclerView/
Apache License 2.0
136 stars 17 forks source link

IndexOutOfBoundsException during an adapter update #153

Closed BelooS closed 1 year ago

BelooS commented 1 year ago

Hello. We've found a crash while DpadRecyclerView's adapter is updated fast

Prerequisites:


java.lang.IndexOutOfBoundsException: Invalid item position -2(-2). 
Item count:1 com.rubensousa.dpadrecyclerview.DpadRecyclerView{5c9bf33 VFE...... ......I. 760,282-1520,1080 #7f0a0406 app:id/searchResultsList}, layout:com.rubensousa.dpadrecyclerview.layoutmanager.PivotLayoutManager@f9ae6d
  at androidx.recyclerview.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:6714)
  at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6688)
  at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6684)
  at com.rubensousa.dpadrecyclerview.layoutmanager.layout.linear.LinearLayoutEngineer.initLayout(LinearLayoutEngineer.kt:63)
  at com.rubensousa.dpadrecyclerview.layoutmanager.layout.StructureEngineer.layoutChildren(StructureEngineer.kt:204)
  at com.rubensousa.dpadrecyclerview.layoutmanager.layout.PivotLayout.layoutChildren(PivotLayout.kt:119)
  at com.rubensousa.dpadrecyclerview.layoutmanager.layout.PivotLayout.onLayoutChildren(PivotLayout.kt:88)
  at com.rubensousa.dpadrecyclerview.layoutmanager.PivotLayoutManager.onLayoutChildren(PivotLayoutManager.kt:126)
  at androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:4604)
  at androidx.recyclerview.widget.RecyclerView.dispatchLayout(RecyclerView.java:4307)
  at androidx.recyclerview.widget.RecyclerView.onLayout(RecyclerView.java:4873)
  at android.view.View.layout(View.java:23694)
  at android.view.ViewGroup.layout(ViewGroup.java:6413)
  at androidx.constraintlayout.widget.ConstraintLayout.onLayout(ConstraintLayout.java:1873)
  at android.view.View.layout(View.java:23694)
rubensousa commented 1 year ago

Thanks for sharing the reproduction steps. I will have a look at this once I have more time. For now, can you fallback to submitList(emptyList()) whenever you enter a search term instead? Can you show me a sequence example of updates you do?

BelooS commented 1 year ago

@rubensousa Hi and ty for the hint. The workaround works if an adapter is reset by submitList(emptyList()) in a previous tick of the change.

For example, we have a filtered simple list of countries. Ukraine, Usa, United Kindgdom, other countries. User may enter U and after 0,5 seconds debounce the updated list is shown, where only Ukraine, Usa and United Kingdom are shown. A user continues their input and adds 'k': 'uk' . With that input only Ukraine and United Kindgdom are shown. Then user can continue the input even to an empty filtered list or go back by pressing backspace button, so the list items count is constantly changing. Do few consequential changes and the crash occurs.

rubensousa commented 1 year ago

I managed to reproduce it and fix the issue. PR here: https://github.com/rubensousa/DpadRecyclerView/pull/154

rubensousa commented 1 year ago

Released in 1.1.0-alpha02! Thanks for the bug report! @BelooS

MRDHR commented 10 months ago

Our app used dpadrecycliew and also encountered IndexOutOfBoundsException,

Using 1.2.0-alpha02.

The following is the stack information when an error occurs

androidx.recyclerview.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:6783) androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6757) androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6753) com.rubensousa.dpadrecyclerview.layoutmanager.layout.linear.LinearLayoutEngineer.initLayout(LinearLayoutEngineer.kt:63) com.rubensousa.dpadrecyclerview.layoutmanager.layout.StructureEngineer.layoutChildren(StructureEngineer.kt:205) com.rubensousa.dpadrecyclerview.layoutmanager.layout.PivotLayout.layoutChildren(PivotLayout.kt:124) com.rubensousa.dpadrecyclerview.layoutmanager.layout.PivotLayout.onLayoutChildren(PivotLayout.kt:89) com.rubensousa.dpadrecyclerview.layoutmanager.PivotLayoutManager.onLayoutChildren(PivotLayoutManager.kt:128) androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:4645) androidx.recyclerview.widget.RecyclerView.dispatchLayout(RecyclerView.java:4348) androidx.recyclerview.widget.RecyclerView.onLayout(RecyclerView.java:4919) android.view.View.layout(View.java:22501) android.view.ViewGroup.layout(ViewGroup.java:6528) android.widget.FrameLayout.layoutChildren(FrameLayout.java:334) android.widget.FrameLayout.onLayout(FrameLayout.java:270) android.view.View.layout(View.java:22501) android.view.ViewGroup.layout(ViewGroup.java:6528) androidx.appcompat.widget.LinearLayoutCompat.setChildFrame(LinearLayoutCompat.java:1669) androidx.appcompat.widget.LinearLayoutCompat.layoutHorizontal(LinearLayoutCompat.java:1658) androidx.appcompat.widget.LinearLayoutCompat.onLayout(LinearLayoutCompat.java:1433) android.view.View.layout(View.java:22501) android.view.ViewGroup.layout(ViewGroup.java:6528) android.widget.FrameLayout.layoutChildren(FrameLayout.java:334) android.widget.FrameLayout.onLayout(FrameLayout.java:270) android.view.View.layout(View.java:22501) android.view.ViewGroup.layout(ViewGroup.java:6528) android.widget.FrameLayout.layoutChildren(FrameLayout.java:334) android.widget.FrameLayout.onLayout(FrameLayout.java:270) android.view.View.layout(View.java:22501) android.view.ViewGroup.layout(ViewGroup.java:6528) razerdp.basepopup.PopupDecorViewProxy.layoutInternal(PopupDecorViewProxy.java:597) razerdp.basepopup.PopupDecorViewProxy.onLayout(PopupDecorViewProxy.java:378) android.view.View.layout(View.java:22501) android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:3276) android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:2235) android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:9043) android.view.Choreographer$CallbackRecord.run(Choreographer.java:1280) android.view.Choreographer.doCallbacks(Choreographer.java:1019) android.view.Choreographer.doFrame(Choreographer.java:911) android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1248) android.os.Handler.handleCallback(Handler.java:900) android.os.Handler.dispatchMessage(Handler.java:103) android.os.Looper.loop(Looper.java:219) android.app.ActivityThread.main(ActivityThread.java:8673) java.lang.reflect.Method.invoke(Native Method) com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:513) com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1109)