ShamylZakariya / StickyHeaders

Adapter and LayoutManager for Android RecyclerView which enables sticky header positioning.
MIT License
1.4k stars 185 forks source link

Crash on scroll during item removal animation #89

Open aleksandra-majchrzak opened 6 years ago

aleksandra-majchrzak commented 6 years ago

In my RecyclerView row I have a button that removes row with default recyclerView slide animation. When I remove a row and during the removal animation I try to swipe the list I get one of below errors (I was not able to determine exactly what action causes which error):

java.lang.RuntimeException: trying to unhide a view that was not hiddenandroid.support.constraint.ConstraintLayout{9f21400 V.E...... ........ 0,487-990,575}
at android.support.v7.widget.ChildHelper.unhide(ChildHelper.java:355)
at android.support.v7.widget.RecyclerView$Recycler.getScrapOrHiddenOrCachedHolderForPosition(RecyclerView.java:6098)
at android.support.v7.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:5601)
at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5563)
at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5559)
at org.zakariya.stickyheaders.StickyHeaderLayoutManager.createSectionHeaderIfNeeded(StickyHeaderLayoutManager.java:277)
at org.zakariya.stickyheaders.StickyHeaderLayoutManager.updateHeaderPositions(StickyHeaderLayoutManager.java:746)
at org.zakariya.stickyheaders.StickyHeaderLayoutManager.scrollVerticallyBy(StickyHeaderLayoutManager.java:433)
at android.support.v7.widget.RecyclerView.scrollByInternal(RecyclerView.java:1758
java.lang.IllegalArgumentException: view is not a child, cannot hide android.support.constraint.ConstraintLayout{c64f7d V.E...... .......D 0,1299-990,1539}
at android.support.v7.widget.ChildHelper.unhide(ChildHelper.java:352)
at android.support.v7.widget.RecyclerView$Recycler.getScrapOrHiddenOrCachedHolderForPosition(RecyclerView.java:6098)
at android.support.v7.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:5601)
at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5563)
at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5559)
at org.zakariya.stickyheaders.StickyHeaderLayoutManager.scrollVerticallyBy(StickyHeaderLayoutManager.java:413)
at android.support.v7.widget.RecyclerView.scrollByInternal(RecyclerView.java:1758) 
java.lang.IndexOutOfBoundsException: adapterPosition (-1) cannot be < 0
at org.zakariya.stickyheaders.SectioningAdapter.getItemViewType(SectioningAdapter.java:1196)
at org.zakariya.stickyheaders.SectioningAdapter.getItemViewBaseType(SectioningAdapter.java:1244)
at org.zakariya.stickyheaders.StickyHeaderLayoutManager.getViewBaseType(StickyHeaderLayoutManager.java:840)
at org.zakariya.stickyheaders.StickyHeaderLayoutManager.createSectionHeaderIfNeeded(StickyHeaderLayoutManager.java:270)
at org.zakariya.stickyheaders.StickyHeaderLayoutManager.updateHeaderPositions(StickyHeaderLayoutManager.java:746)
at org.zakariya.stickyheaders.StickyHeaderLayoutManager.scrollVerticallyBy(StickyHeaderLayoutManager.java:433)
at android.support.v7.widget.RecyclerView.scrollByInternal(RecyclerView.java:1758)

Everything works fine when I wait for the removal animation to end. I use 0.7.6 lib version and I tested it on Xiaomi and Samsung devices. Any hints?

chennanoka commented 6 years ago

Similar situation here, the "View v = recycler.getViewForPosition(adapterPosition);" triggers a crash in recyclerView at "mChildHelper.unhide(view);". And saying "view is not a child, cannot hide". This crash happens randomly after scroll and refrsh the list.

tulioccalazans commented 6 years ago

Is there a way to remove removal animation from this?

tulioccalazans commented 6 years ago

Haha! I found a paliative fix! I know that if you call mAdapter.notifyDataSetChanged while there is an animation ongoing, the animation will stop. So, I did:

recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);
                if(actionMode != null) { // If it is in selection mode
                    adapter.notifyDataSetChanged();
                }
            }
        });

This is only a PALIATIVE FIX. A better solution must be found!

@chennanoka @aleksandra-majchrzak

aleksandra-majchrzak commented 6 years ago

Currently I just turned off the scroll for this short time when removal animation is ongoing. Not the best solution, but for me it's enough.

nashihu commented 4 years ago

any proper solution for this?

nashihu commented 4 years ago

hello @aleksandra-majchrzak could you please share how'd you turn off the scroll in your case? thank you

aleksandra-majchrzak commented 4 years ago

Hi. I don't have the access to that code anymore, but most probably I just created my own LayoutManager like in there: https://stackoverflow.com/questions/30531091/how-to-disable-recyclerview-scrolling and just dynamically change scrolling flag.