代码之家  ›  专栏  ›  技术社区  ›  Coova

ArrayAdapter类的IndexOutOfBoundsException问题

  •  1
  • Coova  · 技术社区  · 10 年前

    我试图弄清楚为什么我会收到以下错误。

    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$1.onPressed(CreateFragment.java:143)
            at com.modup.adapter.WorkoutCardsAdapter$1.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<>,这个Adapter类用于在片段中填充ListView。一切都很好,我可以添加视图,我可以删除视图(某种程度上),我可以访问实现的回调。

    问题: 似乎当我添加许多视图3-4+并开始删除它们时,我最终会遇到这个例外。

    具体情况: 如果我从顶部视图列表项开始,向下看,我似乎不会抛出错误,而且有时也可以从底部向上看。如果我将视图按顺序删除(有时),似乎会出现错误。

    如何解决此问题?我是否错误地重写了getCount()和getItem()?

    更新:

    检查mCallback.onPress(位置)的位置时;它看起来好像列表中第一个项目的位置是0,并且只要我不尝试删除它下面的任何列表项目,它将保持为0。一旦我删除了它下面的列表项目,第一个列表项目将具有完全不同的位置。

    公共类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;
    }
    

    @覆盖 public WorkoutView getItem(最终int位置){ 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();
    
    1 回复  |  直到 10 年前
        1
  •  2
  •   Mike M.    10 年前

    我认为问题是你没有用相应的按钮缓存正确的位置,所以被删除的项目被混淆了。您可以将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);
        }
    });