2

I am facing this crash in HorizontalGridView (RecyclerView) in leanback component

Device: Android TV

Android Version: 9

Logic:

My Adapter extends ListAdapter to which I will submit the list of data, which will internally handles the notification to the adapter using DiffUtils. Whenever a new list of data is received, I am just getting the instance of adapter and submitting the new list of data. Now the ListAdapter will internally notify the changes based on the diff logic. Below is the sample code



    if (myViewHolder.getHorizontalGridView().getAdapter() instanceof MyAdapter) {
        MyAdapter myAdapter = (MyAdapter) myViewHolder.getHorizontalGridView().getAdapter();
        myAdapter.submitList(dataList);
    } else {
        MyAdapter myAdapter = new MyAdapter(context);
        myViewHolder.getHorizontalGridView().setAdapter(myAdapter);
        myAdapter.submitList(dataList);
    }

Whenever any new list of data is getting notified in adapter and when I do the scrolling at the same instant I am facing the below crash.

Crash log:

 

    2021-03-09 10:31:17.213 9746-9746/? E/AndroidRuntime: FATAL EXCEPTION: main
        Process: com.MyApplication.tv, PID: 9746
        java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid item position 9(offset:18).state:17 androidx.leanback.widget.HorizontalGridView{fdd0e8f VFE...... ......ID 0,98-1760,267 #7f0b098b app:id/railID}, adapter:com.MyApplication.tv.adapter.MyAdapter@7447afe, layout:androidx.leanback.widget.GridLayoutManager@415f25f, context:com.MyApplication.tv.MainActivity@358a4f0
            at androidx.recyclerview.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:6183)
            at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6118)
            at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6114)
            at androidx.leanback.widget.GridLayoutManager.getViewForPosition(GridLayoutManager.java:1085)
            at androidx.leanback.widget.GridLayoutManager$2.createItem(GridLayoutManager.java:1613)
            at androidx.leanback.widget.SingleRow.appendVisibleItems(SingleRow.java:113)
            at androidx.leanback.widget.Grid.appendVisibleItems(Grid.java:397)
            at androidx.leanback.widget.GridLayoutManager.appendVisibleItems(GridLayoutManager.java:1934)
            at androidx.leanback.widget.GridLayoutManager.onLayoutChildren(GridLayoutManager.java:2219)
            at androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep1(RecyclerView.java:4085)
            at androidx.recyclerview.widget.RecyclerView.dispatchLayout(RecyclerView.java:3849)
            at androidx.recyclerview.widget.RecyclerView.consumePendingUpdateOperations(RecyclerView.java:1897)
            at androidx.recyclerview.widget.RecyclerView$1.run(RecyclerView.java:414)
            at android.view.Choreographer$CallbackRecord.run(Choreographer.java:949)
            at android.view.Choreographer.doCallbacks(Choreographer.java:761)
            at android.view.Choreographer.doFrame(Choreographer.java:693)
            at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:935)
            at android.os.Handler.handleCallback(Handler.java:873)
            at android.os.Handler.dispatchMessage(Handler.java:99)
            at android.os.Looper.loop(Looper.java:193)
            at android.app.ActivityThread.main(ActivityThread.java:6718)
            at java.lang.reflect.Method.invoke(Native Method)
            at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)

As far as my understanding from this crash, it looks like when RecyclerView could not find the ViewHolder for the position, it internally throws exception. Inside RecyclerView.tryGetViewHolderForPositionByDeadline method looks like (copied from Android Studio)



    // 1) Find by position from scrap/hidden list/cache
    if (holder == null) {
        holder = getScrapOrHiddenOrCachedHolderForPosition(position, dryRun);
        if (holder != null) {
            if (!validateViewHolderForOffsetPosition(holder)) {
                // recycle holder (and unscrap if relevant) since it can't be used
                if (!dryRun) {
                    // we would like to recycle this but need to make sure it is not used by
                    // animation logic etc.
                    holder.addFlags(ViewHolder.FLAG_INVALID);
                    if (holder.isScrap()) {
                        removeDetachedView(holder.itemView, false);
                        holder.unScrap();
                    } else if (holder.wasReturnedFromScrap()) {
                        holder.clearReturnedFromScrapFlag();
                    }
                    recycleViewHolderInternal(holder);
                }
                holder = null;
            } else {
                fromScrapOrHiddenOrCache = true;
            }
        }
    }
    if (holder == null) {
        final int offsetPosition = mAdapterHelper.findPositionOffset(position);
        if (offsetPosition = mAdapter.getItemCount()) {
            throw new IndexOutOfBoundsException ("Inconsistency detected. Invalid item "
                    + "position " + position + "(offset:" + offsetPosition + ")."
                    + "state:" + mState.getItemCount() + exceptionLabel());
        }
    }

I tried the solution from this thread RecyclerView: Inconsistency detected. Invalid item position The solution did not worked for me :(

What would be the solution for this? Would be great if I get to know the solution to handle this or anything I am missing to handle this case :)

Benaka
  • 21
  • 2

0 Answers0