MaterialList
MaterialList copied to clipboard
ArrayIndexOutOfBoundsException in SwipeDismissListener
java.lang.ArrayIndexOutOfBoundsException: length=12; index=-1
at java.util.ArrayList.get(ArrayList.java:310)
at android.widget.ArrayAdapter.getItem(ArrayAdapter.java:337)
at com.dexafree.materialList.controller.SwipeDismissListener.isCurrentItemDismissable(SwipeDismissListener.java:359)
at com.dexafree.materialList.controller.SwipeDismissListener.onTouch(SwipeDismissListener.java:197)
at android.view.View.dispatchTouchEvent(View.java:8382)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2424)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2158)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2430)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2172)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2430)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2172)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2430)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2172)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2430)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2172)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2430)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2172)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2430)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2172)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2430)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2172)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2430)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2172)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2430)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2172)
at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:2314)
at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1692)
at android.app.Activity.dispatchTouchEvent(Activity.java:2739)
at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:2275)
at android.view.View.dispatchPointerEvent(View.java:8578)
at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:4021)
at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:3887)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3449)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3502)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3468)
at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:3578)
at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3476)
at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:3635)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3449)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3502)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3468)
at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3476)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3449)
at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:5701)
at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:5675)
at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:5646)
at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:5791)
at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:185)
at android.os.MessageQueue.nativePollOnce(Native Method)
at android.os.MessageQueue.next(MessageQueue.java:143)
at android.os.Looper.loop(Looper.java:122)
at android.app.ActivityThread.main(ActivityThread.java:5221)
at java.lang.reflect.Method.invoke(Nati
I've got the same exception in another context. See #24
The Exception I got is fixed with my Pull Request #23. Could you try, if it is also fixed for you?
To me it looks like the underlying array list that holds the models is not correctly updated. E.g. there is no place in the code where you ever call mAdapter.remove()
I'm just playing around with onCardDismiss
method in MaterialListView
:
@Subscribe
public void onCardDismiss(DismissEvent event){
Card dismissedCard = event.getDismissedCard();
View dismissedCardView = null;
for (int index = 0; index < getCount(); index++) {
View view = getChildAt(index);
if(view != null && view.getTag() != null && view.getTag().equals(dismissedCard)) { //add null check on view itself
dismissedCardView = view;
break;
}
}
if(dismissedCardView != null) {
mDismissListener.dismissCard(dismissedCardView, dismissedCard);
}
mAdapter.remove(dismissedCard); //Actually remove dismissed model (card) from ArrayList
}
Adding the null check on view itself helped me avoiding the following Runtime / Nullpointer Exceptions that occured when I updated the model asynchronously.
java.lang.RuntimeException: Could not dispatch event: class com.dexafree.materialList.events.DismissEvent to handler [EventHandler public void com.dexafree.materialList.view.MaterialListView.onCardDismiss(com.dexafree.materialList.events.DismissEvent)]: Attempt to invoke virtual method 'java.lang.Object android.view.View.getTag()' on a null object reference
at com.squareup.otto.Bus.throwRuntimeException(Bus.java:456)
at com.squareup.otto.Bus.dispatch(Bus.java:386)
at com.squareup.otto.Bus.dispatchQueuedEvents(Bus.java:367)
at com.squareup.otto.Bus.post(Bus.java:336)
at com.dexafree.materialList.events.MainThreadBus.post(MainThreadBus.java:31)
at com.dexafree.materialList.events.BusProvider.dismiss(BusProvider.java:22)
at com.blockconsult.nominator.MainActivity$2.onButtonPressedListener(MainActivity.java:106)
at com.dexafree.materialList.cards.view.BaseButtonsCardItemView$1.onClick(BaseButtonsCardItemView.java:41)
at android.view.View.performClick(View.java:4756)
at android.view.View$PerformClick.run(View.java:19749)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5221)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.Object android.view.View.getTag()' on a null object reference
at com.dexafree.materialList.view.MaterialListView.onCardDismiss(MaterialListView.java:164)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.squareup.otto.EventHandler.handleEvent(EventHandler.java:89)
at com.squareup.otto.Bus.dispatch(Bus.java:384)
at com.squareup.otto.Bus.dispatchQueuedEvents(Bus.java:367)
at com.squareup.otto.Bus.post(Bus.java:336)
at com.dexafree.materialList.events.MainThreadBus.post(MainThreadBus.java:31)
at com.dexafree.materialList.events.BusProvider.dismiss(BusProvider.java:22)
at com.blockconsult.nominator.MainActivity$2.onButtonPressedListener(MainActivity.java:106)
at com.dexafree.materialList.cards.view.BaseButtonsCardItemView$1.onClick(BaseButtonsCardItemView.java:41)
at android.view.View.performClick(View.java:4756)
at android.view.View$PerformClick.run(View.java:19749)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5221)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
Also I added the mAdapter.remove(card)
call to actually update the underlying array list that holds the models (cards).
To me this still feels hacky as I do not (yet) understand where model <-> view synchronization is supposed to happen but at least I have no more exceptions in my app.
...ok. I was too fast. After the above updates the underlying model list is now seriously broken. Maybe some of you guys has a better idea. I guess one of the problems is that most real life implementations load the data asynchronously (e.g. making network calls inside UIThread to load data is prohibited). But the current implementation seems to be not thread safe.
@FHellmann I adapt your modifications, now this exception will not be thrown. Thanks. However I got another bug, Please help me. If I swipe out the card from the bottom up, it works totally fine. However, If I swipe out the card from the top down or any other way (except the bottom-up way), I got this following bug:
Here is the Java Code for My Card: SnapNoteMainCard
Here is the Java Code for My Card View: SnapNoteMainCardItemView
@cblock The Call to remove a card from the Adapter is inside of the OnDismissCallback. You're right. Currently the Adapter is not Thread save. I will fix this after my exams, or maybe you create a Pull Request. ;-)
@eeandrew Your Bug does not come from your Card Code. Dismissing the Card will be called from the SwipeDismissListener which calls the OnDismissCallback where the Card will be removed then. I can't explain this behavior to me. I will take a look at this Bug as soon I will find the time.
@FHellmann It seems the layout is changed from RelativeLayout to LinearLayout.
I am also still having this issue when swiping away cards. Was this marked as fixed?
I get this exception and I'm not using the Swipe ability or the OnDismissCallback. It's hard for me to replicate what causes this.
java.lang.ArrayIndexOutOfBoundsException: length=12; index=-1
at java.util.ArrayList.get(ArrayList.java:310)
at com.dexafree.materialList.controller.MaterialListAdapter.getCard(MaterialListAdapter.java:97)
at com.dexafree.materialList.view.MaterialListView$2.canDismiss(MaterialListView.java:62)
at com.dexafree.materialList.controller.SwipeDismissRecyclerViewTouchListener.onTouch(SwipeDismissRecyclerViewTouchListener.java:212)
at android.view.View.dispatchTouchEvent(View.java:8382)
@maarek do you already use the current version (3.0.1) of MaterialList?
@FHellmann No. On 2.4.5. Found out last night why I was having issues with this. One word: Threads. The cards were being refreshed (cleared and readded) on a background thread.This caused all of the arraylist issues I have been seeing in the adapter.