h6ah4i / android-advancedrecyclerview

RecyclerView extension library which provides advanced features. (ex. Google's Inbox app like swiping, Play Music app like drag and drop sorting)
https://advancedrecyclerview.h6ah4i.com/
Apache License 2.0
5.32k stars 862 forks source link

IllegalStateException onMoveItem() despite having stable IDs #88

Closed cabbage closed 9 years ago

cabbage commented 9 years ago

Hi,

I know that issue #10 is about the same error, but since it's closed and a bit older I'll start with a new one.

It's fairly easy to reproduce but not to understand (for me at least). When starting the Activity (it has a ViewPager and the RecyclerView is in one of the Fragments acting as pages) dragging the item views is not a problem. However, when I click an Item and start another Activity and then return to the RecyclerView and start dragging I get this IllegalStateException:

08-14 16:45:22.236  28650    28650         AndroidRuntime  E  FATAL EXCEPTION: main
08-14 16:45:22.236  28650    28650         AndroidRuntime  E  Process: com.nextmarkets.next.local, PID: 28650
08-14 16:45:22.236  28650    28650         AndroidRuntime  E  java.lang.IllegalStateException: onMoveItem() - may be a bug or has duplicate IDs  --- mDraggingItemInitialPosition = 2, mDraggingItemCurrentPosition = 3, origFromPosition = 3, fromPosition = 2, toPosition = 3
08-14 16:45:22.236  28650    28650         AndroidRuntime  E  at com.h6ah4i.android.widget.advrecyclerview.draggable.DraggableItemWrapperAdapter.moveItem(DraggableItemWrapperAdapter.java:326)
08-14 16:45:22.236  28650    28650         AndroidRuntime  E  at com.h6ah4i.android.widget.advrecyclerview.draggable.RecyclerViewDragDropManager.swapItems(RecyclerViewDragDropManager.java:1100)
08-14 16:45:22.236  28650    28650         AndroidRuntime  E  at com.h6ah4i.android.widget.advrecyclerview.draggable.RecyclerViewDragDropManager.checkItemSwapping(RecyclerViewDragDropManager.java:862)
08-14 16:45:22.236  28650    28650         AndroidRuntime  E  at com.h6ah4i.android.widget.advrecyclerview.draggable.RecyclerViewDragDropManager.access$400(RecyclerViewDragDropManager.java:44)
08-14 16:45:22.236  28650    28650         AndroidRuntime  E  at com.h6ah4i.android.widget.advrecyclerview.draggable.RecyclerViewDragDropManager$4.run(RecyclerViewDragDropManager.java:1005)
08-14 16:45:22.236  28650    28650         AndroidRuntime  E  at android.view.Choreographer$CallbackRecord.run(Choreographer.java:777)
08-14 16:45:22.236  28650    28650         AndroidRuntime  E  at android.view.Choreographer.doCallbacks(Choreographer.java:590)
08-14 16:45:22.236  28650    28650         AndroidRuntime  E  at android.view.Choreographer.doFrame(Choreographer.java:559)
08-14 16:45:22.236  28650    28650         AndroidRuntime  E  at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:763)
08-14 16:45:22.236  28650    28650         AndroidRuntime  E  at android.os.Handler.handleCallback(Handler.java:739)
08-14 16:45:22.236  28650    28650         AndroidRuntime  E  at android.os.Handler.dispatchMessage(Handler.java:95)
08-14 16:45:22.236  28650    28650         AndroidRuntime  E  at android.os.Looper.loop(Looper.java:145)
08-14 16:45:22.236  28650    28650         AndroidRuntime  E  at android.app.ActivityThread.main(ActivityThread.java:5832)
08-14 16:45:22.236  28650    28650         AndroidRuntime  E  at java.lang.reflect.Method.invoke(Native Method)
08-14 16:45:22.236  28650    28650         AndroidRuntime  E  at java.lang.reflect.Method.invoke(Method.java:372)
08-14 16:45:22.236  28650    28650         AndroidRuntime  E  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399)
08-14 16:45:22.236  28650    28650         AndroidRuntime  E  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194)

Is there anything I might be missing?

cabbage commented 9 years ago

As I learned right now, this does not only happen when I start a new Activity, but also when I lock the phone or generally leave the app and return to that screen. Another weird behaviour which is triggered by pausing/stopping the app is that when I swipe to delete the background drawable is visibly placed on the whole container instead of just the swipe-area (if that makes sense) Unfortunately I think I cannot provide screenshots due to our NDA.

But here are some implementation details: The RecyclerView.Adapter is created & injected by dagger in onActivityCreated() and set to the RecyclerView in onStart() (after wrapping the adapter of course and initialising the swipe/drag'n'drop/touchguard managers). After that the Presenter loads the data into the Adapter.

h6ah4i commented 9 years ago

Hi. When do you call the RecyclerViewDragDropManager.release() method? Initializing the RecyclerViewDragDropManager multiple times without calling the release() method may cause such problems.

Need to take care that View instances (of course including the RecyclerView) are kept alive even after the current Activity becomes background, so the same RecyclerView instance will be reused after returning the newly opened Activity.

Related post on StackOverflow:

cabbage commented 9 years ago

Indeed I did release them in onDestroy() - I changed that to onStop() and it's working now.

Thanks a lot! That SO question was really enlightening :+1: