为什么在我的对话框中调用 activity 方法时会出现 IndexOutOfBoundsException 错误?
Why am I getting an IndexOutOfBoundsException error when calling an activity method from my dialog?
我有一个充满项目的 Recycler View,当您长按一行时,会出现一个删除按钮以允许用户删除该行 - 我设法让它正常工作,但我想添加一点通过添加一个对话框询问用户是否要删除该行来确保安全。但是,当我在对话框中调用该方法时,我得到如下 IndexOutOfBoundsException
:
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$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)
我正在使用界面长按回收站视图行:
package com.example.it_stock;
public interface StockViewInterface {
void onItemClick(int position);
void onLongItemClick(int position);
}
这是在我的适配器中:
// 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.
});
这些是我的 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();
}
当我在 yes()
方法的对话框中调用 deleteItemRow()
方法时出现问题:
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();
});
}
}
如开头所述,如果我在删除项目按钮上调用它,deleteItemRow()
将正常工作,如果我这样做:
@Override
public void onLongItemClick(int position) {
btnRemoveItem.setVisibility(View.VISIBLE);
btnRemoveItem.setOnClickListener(v -> {
deleteItemRow(position);
});
System.out.println(position);
}
我已经使用 System.out
行来确保 position
是正确的。
任何人都可以帮助我理解为什么从我的对话框调用方法时列表是空的,但如果我在我的 main activity 中调用它却不是空的。有没有办法解决这个问题?提前致谢。
编辑:当从对话框调用该方法时,我的 allStock
ArrayList 为空。这就是我获取 ArrayList 的方式:
private DBHandlerStock db;
private ArrayList<Stock> allStock = new ArrayList<>();
db = new DBHandlerStock(this);
allStock = db.getAllStock();
我通过将 DBHandler、ArrayList、Adapter 和 Button 设置为静态来设法 'fix' 做到这一点。然而,这会造成内存泄漏,所以我将找到另一种方法来解决它。谢谢你的回复。
编辑:我只需要在我的对话框中将 mainActivity = new MainActivity();
更改为 mainActivity = ((MainActivity)getActivity());
。 arrayList
是空的,因为每次打开对话框时它都会创建一个新的 mainActivity。
我有一个充满项目的 Recycler View,当您长按一行时,会出现一个删除按钮以允许用户删除该行 - 我设法让它正常工作,但我想添加一点通过添加一个对话框询问用户是否要删除该行来确保安全。但是,当我在对话框中调用该方法时,我得到如下 IndexOutOfBoundsException
:
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$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)
我正在使用界面长按回收站视图行:
package com.example.it_stock;
public interface StockViewInterface {
void onItemClick(int position);
void onLongItemClick(int position);
}
这是在我的适配器中:
// 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.
});
这些是我的 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();
}
当我在 yes()
方法的对话框中调用 deleteItemRow()
方法时出现问题:
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();
});
}
}
如开头所述,如果我在删除项目按钮上调用它,deleteItemRow()
将正常工作,如果我这样做:
@Override
public void onLongItemClick(int position) {
btnRemoveItem.setVisibility(View.VISIBLE);
btnRemoveItem.setOnClickListener(v -> {
deleteItemRow(position);
});
System.out.println(position);
}
我已经使用 System.out
行来确保 position
是正确的。
任何人都可以帮助我理解为什么从我的对话框调用方法时列表是空的,但如果我在我的 main activity 中调用它却不是空的。有没有办法解决这个问题?提前致谢。
编辑:当从对话框调用该方法时,我的 allStock
ArrayList 为空。这就是我获取 ArrayList 的方式:
private DBHandlerStock db;
private ArrayList<Stock> allStock = new ArrayList<>();
db = new DBHandlerStock(this);
allStock = db.getAllStock();
我通过将 DBHandler、ArrayList、Adapter 和 Button 设置为静态来设法 'fix' 做到这一点。然而,这会造成内存泄漏,所以我将找到另一种方法来解决它。谢谢你的回复。
编辑:我只需要在我的对话框中将 mainActivity = new MainActivity();
更改为 mainActivity = ((MainActivity)getActivity());
。 arrayList
是空的,因为每次打开对话框时它都会创建一个新的 mainActivity。