I have a RecyclerView list of CardViews. A click on the CardView loads a DetailsActivity for that CardView, using its position in the RecyclerView list. Recently a click on CardView crashed the app with an ArrayIndexOutOfBoundsException. I did click on the CardView quickly after returning to the Recycler list UI, so might this be some type of asynchronous error. Any thoughts on how to fix?
Code for the item click in the RecyclerView's CardsAdapter:
public List<Card> mListItems;
...
public Card getItem(int position) {
**return mListItems.get(position); // line 102**
}
ClickListener code in the CardsAdapter to handle the item click:
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = layoutInflater.inflate(R.layout.item_todo, parent,false);
final ItemHolder itemHolder = new ItemHolder(itemView);
itemHolder.cardView.setOnClickListener(view -> {
**Card adapterItem = CardsAdapter.this.getItem(itemHolder.getBindingAdapterPosition()); // line 639**
int adapPos = itemHolder.getBindingAdapterPosition();
if (adapPos == RecyclerView.NO_POSITION || recyclerItemClickListener == null) {
return;
}
recyclerItemClickListener.onItemClick(itemHolder.cardView, adapterItem, adapPos);
});
...
}
Logcat:
E/AndroidRuntime: FATAL EXCEPTION: main Process: com.todo.quickcards, PID: 10677 java.lang.ArrayIndexOutOfBoundsException: length=36; index=-1 at java.util.ArrayList.get(ArrayList.java:439) at com.todo.quickcards.adapter.CardsAdapter.getItem(CardsAdapter.java:102) at com.todo.quickcards.adapter.CardsAdapter.lambda$onCreateViewHolder$0$com-todo-quickcards-adapter-CardsAdapter(CardsAdapter.java:639) at com.todo.quickcards.adapter.CardsAdapter$$ExternalSyntheticLambda0.onClick(Unknown Source:4) at android.view.View.performClick(View.java:6897) at android.view.View$PerformClick.run(View.java:26101) at android.os.Handler.handleCallback(Handler.java:789) at android.os.Handler.dispatchMessage(Handler.java:98) at android.os.Looper.loop(Looper.java:164) at android.app.ActivityThread.main(ActivityThread.java:6944) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:327) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1374)
If you are gonna call getItem(itemHolder.getBindingAdapterPosition())
then better call it after/inside the Condition check . Which checked for invalid position .
int adapPosition = itemHolder.getBindingAdapterPosition();
if (adapPos == RecyclerView.NO_POSITION || recyclerItemClickListener == null) {
return;
}
Card adapterItem = CardsAdapter.this.getItem(adapPosition);
recyclerItemClickListener.onItemClick(itemHolder.cardView, adapterItem, adapPos);