I have a Recycler View full of items, when you long press on a row, a remove buttons appears to allow the user to delete the row - I managed to get that working correctly but I then wanted to add a bit of safety to it by adding a dialog which asks the user whether or not they want to delete the row. However when I call the method in my dialog I get an IndexOutOfBoundsException
as below:
2021-10-19 15:52:06.774 16238-16238/com.example.it_stock E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.it_stock, PID: 16238
java.lang.IndexOutOfBoundsException: Index: 6, Size: 0
at java.util.ArrayList.get(ArrayList.java:411)
at com.example.it_stock.MainActivity.deleteItemRow(MainActivity.java:93)
at com.example.it_stock.ConfirmDeleteDialog.lambda$yes$1$ConfirmDeleteDialog(ConfirmDeleteDialog.java:48)
at com.example.it_stock.-$$Lambda$ConfirmDeleteDialog$VgpDlH3zTD1jVLwQl8Gp5RaCjYw.onClick(lambda)
at android.view.View.performClick(View.java:5637)
at com.google.android.material.button.MaterialButton.performClick(MaterialButton.java:1119)
at android.view.View$PerformClick.run(View.java:22433)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6121)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:889)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:779)
I am using an interface to long click on the recycler view rows:
package com.example.it_stock;
public interface StockViewInterface {
void onItemClick(int position);
void onLongItemClick(int position);
}
This is in my Adapter:
// Uses the StockViewInterface to implement click listeners. These can then be used in Main Activity.
stockView.setOnClickListener(v -> {
stockViewInterface.onItemClick(getAdapterPosition());
notifyItemChanged(selectedPosition);
selectedPosition = RecyclerView.NO_POSITION;
notifyItemChanged(selectedPosition);
});
stockView.setOnLongClickListener(v -> {
stockViewInterface.onLongItemClick(getAdapterPosition());
// Highlight row
notifyItemChanged(selectedPosition);
selectedPosition = getAdapterPosition();
notifyItemChanged(selectedPosition);
return true; // doesn't allow multiple rows to be selected. False would highlight multiple rows but the remove method only allows one deletion at a time for now.
});
These are the long click and delete row methods in my Main Activity:
// Long tap on a row in the Recycler View. Remove button becomes visible and once clicked opens the confirmation dialog.
@Override
public void onLongItemClick(int position) {
btnRemoveItem.setVisibility(View.VISIBLE);
btnRemoveItem.setOnClickListener(v -> {
ConfirmDeleteDialog confirmDeleteDialog = new ConfirmDeleteDialog();
Bundle bundle = new Bundle();
bundle.putInt("position", position);
confirmDeleteDialog.setArguments(bundle);
confirmDeleteDialog.show((MainActivity.this).getSupportFragmentManager(),"confirm");
});
System.out.println(position);
}
// Deletes row.
public void deleteItemRow(int position) {
String stock = allStock.get(position).getItem();
db.deleteStockItem(db.getStockItem(allStock.get(position).getID()));
allStock.remove(position);
stockAdapter.notifyItemRemoved(position);
stockAdapter.notifyDataSetChanged();
btnRemoveItem.setVisibility(View.INVISIBLE);
stockAdapter.selectedPosition = RecyclerView.NO_POSITION;
Toast.makeText(this, stock + " successfully deleted!", Toast.LENGTH_SHORT).show();
}
The issue occurs in that deleteItemRow()
method when I call it from my Dialog in the yes()
method:
public class ConfirmDeleteDialog extends DialogFragment {
private MainActivity mainActivity;
public static final String TAG = "confirm";
int position;
Button no, yes;
@NonNull
@Override
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
LayoutInflater inflater = getActivity().getLayoutInflater();
View v = inflater.inflate(R.layout.dialog_confirm_delete, null);
Bundle bundle = getArguments();
position = bundle.getInt("position", position);
no = v.findViewById(R.id.btnNo);
yes = v.findViewById(R.id.btnYes);
mainActivity = new MainActivity();
System.out.println(position);
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setView(v);
no();
yes();
return builder.create();
}
private void no() {
no.setOnClickListener(v -> {
dismiss();
});
}
private void yes() {
yes.setOnClickListener(v -> {
mainActivity.deleteItemRow(position);
System.out.println(position);
dismiss();
});
}
}
As mentioned at the start, the deleteItemRow()
works correctly if I call it on the remove item button press if I do this:
@Override
public void onLongItemClick(int position) {
btnRemoveItem.setVisibility(View.VISIBLE);
btnRemoveItem.setOnClickListener(v -> {
deleteItemRow(position);
});
System.out.println(position);
}
I have used the System.out
lines to makes sure position
is correct.
Can anyone help me understand why the list is empty when calling the method from my dialog but isn't empty if I call it in my main activity. And is there a way to fix this? Thanks in advance.
EDIT: My allStock
ArrayList is empty when the method is called from the dialog. This is how I get the ArrayList:
private DBHandlerStock db;
private ArrayList<Stock> allStock = new ArrayList<>();
db = new DBHandlerStock(this);
allStock = db.getAllStock();