ArrayAdapter 的 IndexOutOfBoundsException 问题 Class
IndexOutOfBoundsException issue with ArrayAdapter Class
我想弄清楚为什么会收到以下错误。
java.lang.IndexOutOfBoundsException: Invalid index 2, size is 2
at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:255)
at java.util.ArrayList.get(ArrayList.java:308)
at com.modup.adapter.WorkoutCardsAdapter.getItem(WorkoutCardsAdapter.java:75)
at com.modup.fragment.CreateFragment.onPressed(CreateFragment.java:143)
at com.modup.adapter.WorkoutCardsAdapter.onClick(WorkoutCardsAdapter.java:62)
at android.view.View.performClick(View.java:4442)
at android.view.View$PerformClick.run(View.java:18473)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5105)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:792)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:608)
at dalvik.system.NativeStart.main(Native Method)
我看过很多关于这个主题的帖子,但他们似乎都有相同的答案,并且在实施这些答案后,问题似乎仍然存在。
我的案例:
我有一个扩展 ArrayAdapter<> 的 class,这个适配器 class 用于在我的片段中填充一个 ListView。一切正常,我可以添加视图,我可以删除视图(某种程度上),我可以访问实现的回调。
问题: 似乎当我添加许多视图 3-4+ 并开始删除它们时,我最终会遇到此异常。
具体案例: 如果我从顶部视图列表项开始,然后往下看,我似乎不会抛出错误,而且有时我也可以从下往上看。如果我不按顺序删除视图(有时),似乎会出现错误。
我该如何解决这个问题?我是否错误地覆盖了 getCount() 和 getItem()?
更新:
检查mCallback.onPress(position)的位置时;看起来列表中第一项的位置好像是 0,只要我不尝试删除它下面的任何列表项,它就会保持为 0。一旦我删除了它下面的一个列表项,第一个列表项将有一个完全不同的位置。
public class WorkoutCardsAdapter 扩展 ArrayAdapter {
private LayoutInflater mInflater;
private String[] repArray, setArray, mgArray;
String TAG = WorkoutCardsAdapter.class.getCanonicalName();
Callback mCallback;
List<WorkoutView> mViews;
public WorkoutCardsAdapter(Context context, List<WorkoutView> views, Callback callback) {
super(context, 0, views);
mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mCallback = callback;
this.mViews = views;
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
final ViewHolder holder;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.single_workout_layout, parent, false);
holder = new ViewHolder();
holder.spinnerReps = (Spinner) convertView.findViewById(R.id.spinnerReps);
holder.spinnerSets = (Spinner) convertView.findViewById(R.id.spinnerSets);
holder.spinnerMuscleGroup = (Spinner) convertView.findViewById(R.id.spinnerWorkoutGroup);
holder.etWorkoutName = (EditText) convertView.findViewById(R.id.etWorkoutName);
holder.btnRemoveWorkout = (Button) convertView.findViewById(R.id.btnRemoveWorkout);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.btnRemoveWorkout.setTag(position);
mgArray = getContext().getResources().getStringArray(R.array.string_array_muscle_groups);
TextSpinnerAdapter adapter = new TextSpinnerAdapter(getContext(), R.layout.spinner_text_item, mgArray);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
holder.spinnerMuscleGroup.setAdapter(adapter);
setArray = getContext().getResources().getStringArray(R.array.string_array_sets);
TextSpinnerAdapter adapter1 = new TextSpinnerAdapter(getContext(), R.layout.spinner_text_item, setArray);
adapter1.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
holder.spinnerSets.setAdapter(adapter1);
repArray = getContext().getResources().getStringArray(R.array.string_array_reps);
TextSpinnerAdapter adapter2 = new TextSpinnerAdapter(getContext(), R.layout.spinner_text_item, repArray);
adapter2.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
holder.spinnerReps.setAdapter(adapter2);
holder.btnRemoveWorkout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int position = (Integer) v.getTag();
mCallback.onPressed(position);
}
});
return convertView;
}
@Override public WorkoutView getItem(最终整数位置){ return mViews.get(位置); }
@Override
public int getCount() {
return mViews.size();
}
public interface Callback {
void onPressed(int pos);
}
private static class ViewHolder {
public Spinner spinnerMuscleGroup;
public Spinner spinnerSets;
public Spinner spinnerReps;
public EditText etWorkoutName;
public Button btnRemoveWorkout;
}
}
这是带回调的适配器实现
mWorkoutCardsAdapter = new WorkoutCardsAdapter(getActivity(), mArrayList, new WorkoutCardsAdapter.Callback() {
@Override
public void onPressed(int pos) {
mWorkoutCardsAdapter.remove(mWorkoutCardsAdapter.getItem(pos));
mWorkoutCardsAdapter.notifyDataSetChanged();
}
});
以防万一,这就是我在按下按钮时添加新视图的方式
workoutView = new WorkoutView(getActivity());
mWorkoutCardsAdapter.add(workoutView);
mWorkoutCardsAdapter.notifyDataSetChanged();
我认为问题在于您没有使用相应的 Button 缓存正确的位置,因此被删除的项目混淆了。您可以将按钮的标签设置到该位置,并从传递给 onClick()
方法的视图中检索它,以确保从列表中删除正确的标签。
holder.btnRemoveWorkout.setTag(position);
holder.btnRemoveWorkout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int position = (Integer) v.getTag();
mCallback.onPressed(position);
}
});