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

RecyclerViewSwipeManager crash #229

Open ivandamyanov opened 8 years ago

ivandamyanov commented 8 years ago

If I start swiping an item and I move my finger not at least 90% accurately left or right, I get this exception. So maybe if I move it up a little as well or if I just return the item to its original position, sometimes I get this exception and the app restarts itself:

the IllegalStateException in your code for the SwipeManager

private static void verifyAfterReaction(int result, int afterReaction) { if ((afterReaction == AFTER_SWIPE_REACTION_MOVE_TO_SWIPED_DIRECTION) || (afterReaction == AFTER_SWIPE_REACTION_REMOVE_ITEM)) { switch (result) { case RESULT_SWIPED_LEFT: case RESULT_SWIPED_UP: case RESULT_SWIPED_RIGHT: case RESULT_SWIPED_DOWN: break; default: throw new IllegalStateException("Unexpected after reaction has been requested: result = " + result +", afterReaction = " + afterReaction); } } }

Any idea what could cause this error? My stack trace starts with those lines:

java.lang.IllegalStateException: Unexpected after reaction has been requested: result = 1, afterReaction = 1 at com.h6ah4i.android.widget.advrecyclerview.swipeable.RecyclerViewSwipeManager.verifyAfterReaction(RecyclerViewSwipeManager.java:673) at com.h6ah4i.android.widget.advrecyclerview.swipeable.RecyclerViewSwipeManager.finishSwiping(RecyclerViewSwipeManager.java:609) at com.h6ah4i.android.widget.advrecyclerview.swipeable.RecyclerViewSwipeManager.handleActionUpOrCancelWhileSwiping(RecyclerViewSwipeManager.java:438) at com.h6ah4i.android.widget.advrecyclerview.swipeable.RecyclerViewSwipeManager.handleActionUpOrCancel(RecyclerViewSwipeManager.java:384) at com.h6ah4i.android.widget.advrecyclerview.swipeable.RecyclerViewSwipeManager.onTouchEvent(RecyclerViewSwipeManager.java:309) at com.h6ah4i.android.widget.advrecyclerview.swipeable.RecyclerViewSwipeManager$1.onTouchEvent(RecyclerViewSwipeManager.java:119) at android.support.v7.widget.RecyclerView.dispatchOnItemTouch(RecyclerView.java:2221) at android.support.v7.widget.RecyclerView.onTouchEvent(RecyclerView.java:2364)

h6ah4i commented 8 years ago

Hi. It seems an implementation fault of the onSwipeItem() in your adapter.

If the result argument of the method is RESULT_CANCELED, the method have to return null or an instance of SwipeResultActionDefault extended class.

Good cases

// pattern 1:
@Override
public SwipeResultAction onSwipeItem(MyViewHolder holder, final int position, int result) {
    if (result == Swipeable.RESULT_CANCELED) {
        return null;
    }
    ...
}

// pattern 2
@Override
public SwipeResultAction onSwipeItem(MyViewHolder holder, final int position, int result) {
    if (result == Swipeable.RESULT_CANCELED) {
        return new SwipeResultActionDefault();
    }
    ...
}

// pattern 3
static class MyCanceledResultAction extends SwipeResultActionDefault {
}

@Override
public SwipeResultAction onSwipeItem(MyViewHolder holder, final int position, int result) {
    if (result == Swipeable.RESULT_CANCELED) {
        return new MyCanceledResultAction();
    }
    ...
}

Bad cases

// pattern 4
@Override
public SwipeResultAction onSwipeItem(MyViewHolder holder, final int position, int result) {
    if (result == Swipeable.RESULT_CANCELED) {
        return new SwipeResultActionRemoveItem();
    }
    ...
}

// pattern 5
@Override
public SwipeResultAction onSwipeItem(MyViewHolder holder, final int position, int result) {
    if (result == Swipeable.RESULT_CANCELED) {
        return new SwipeResultActionMoveToSwipedDirection();
    }
    ...
}

Refer the following link for the actual code in the demo app. Thanks!

https://github.com/h6ah4i/android-advancedrecyclerview/blob/0.8.7/example/src/main/java/com/h6ah4i/android/example/advrecyclerview/demo_s_basic/SwipeableExampleAdapter.java#L205