-2

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();
Abhimanyu
  • 11,351
  • 7
  • 51
  • 121
rholmes97
  • 1
  • 5
  • `java.lang.IndexOutOfBoundsException: Index: 6, Size: 0` it's pretty self explainatory: the list is empty and the code is trying to access index `6` – fantaghirocco Oct 19 '21 at 15:21
  • No, I understand what the error is saying. What I don't understand is why the list is empty when calling the method from my dialog but isn't empty if I call it in my main activity. – rholmes97 Oct 19 '21 at 15:28
  • In your `yes()` function, how do you get the `position` variable. I'm sure it works for the first time though. You need to make sure to update/get the variable correctly. – Darkman Oct 19 '21 at 15:35
  • Yes, where are you calling deleteItemRow? Can we see that code? – Kristy Welsh Oct 19 '21 at 15:39
  • @Darkman I get the position using the recycler view position. So the 4th item will be position = 3. I then pass that to the dialog using a bundle. At this point the position is correct because I've used system outs to check. There's also a system out in the yes function which tells me that it's correct at that point too. The issue seems to be my ArrayList is empty if I use the ```deleteItemRow``` function in my dialog instead of my main activity but I can't figure out why. – rholmes97 Oct 19 '21 at 15:50
  • @KristyWelsh It's called in my dialog using ```mainActivity.deleteItemRow(position)``` in the ```yes()``` function (It's already in the body of the question). – rholmes97 Oct 19 '21 at 15:52
  • Print the `allStock` size. I'm sure this was the problem. – Darkman Oct 19 '21 at 15:55

1 Answers1

0

I managed to 'fix' this by making my DBHandler, ArrayList, Adapter and Button static. However this creates memory leaks so I'm going to find another way round it. Thanks for the replies though.

Edit: I just had to change mainActivity = new MainActivity(); to mainActivity = ((MainActivity)getActivity()); in my Dialog. The arrayList was empty because it was creating a new mainActivity every time the dialog was opened.

rholmes97
  • 1
  • 5
  • 1
    Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Oct 19 '21 at 18:43