从ListView中删除项目时IndexOutofBound错误

时间:2012-09-11 18:55:30

标签: android listview

我几乎搜索了与此主题相关的所有可能问题,但无法解决此问题。每当我尝试通过嵌入了ListView项目的自定义删除按钮删除项目时,删除几个项目后,它会给出IndexOutOfBound错误的错误。我知道这个错误即将到来,因为列表无法在项目被移除位置后自行刷新。这是我的代码:

MainActivity:

import java.util.ArrayList;
import java.util.List;

import android.os.Bundle;
import android.app.Activity;
import android.app.ListActivity;
import android.view.Menu;
import android.widget.ArrayAdapter;

public class MainActivity extends ListActivity 
{

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //setContentView(R.layout.activity_main);

        ArrayAdapter<Model> adapter = new InteractiveArrayAdapter(this,getModel());
            //adapter.clear();
        setListAdapter(adapter);
    }

    private List<Model> getModel() {
        List<Model> list = new ArrayList<Model>();
        list.add(get("Linux"));
        list.add(get("Windows7"));
        list.add(get("Suse"));
        list.add(get("Eclipse"));
        list.add(get("Ubuntu"));
        list.add(get("Solaris"));
        list.add(get("Android"));
        list.add(get("iPhone"));
        // Initially select one of the items
        //list.get(1).setSelected(true);
        return list;
      }

    private Model get(String s)
    {
        return new Model(s);
    }

}

InteractiveArrayAdapter.java的代码:

public class InteractiveArrayAdapter extends ArrayAdapter<Model> {

    private final List<Model> list;
    private final Activity context;
    private ListView lv;
    private MainActivity ma;


    public InteractiveArrayAdapter(Activity context, List<Model> list)
    {
        super(context, R.layout.rowbuttonlayout, list);
        this.context = context;
        this.list = list;
    }

    static class ViewHolder
    {
        protected TextView text;
        protected Button btn;
    }

    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {
        View view = null;

        if (convertView == null) 
        {
            LayoutInflater inflator = context.getLayoutInflater();
            view = inflator.inflate(R.layout.rowbuttonlayout, null);


            final ViewHolder viewHolder = new ViewHolder();

            viewHolder.text = (TextView) view.findViewById(R.id.label);
            viewHolder.btn = (Button) view.findViewById(R.id.button1);

            viewHolder.btn.setOnClickListener(new OnClickListener()
            {
                public void onClick(View v)
                {

                        list.remove(position);
                        notifyDataSetChanged();  

                }

            });

            view.setTag(viewHolder);
            viewHolder.btn.setTag(list.get(position));
        } //when convertView = null
        else 
        {
            view = convertView;
            ((ViewHolder) view.getTag()).btn.setTag(list.get(position));
            //((ViewHolder) view.getTag()).text.setTag(list.get(position));
        }
        ViewHolder holder = (ViewHolder) view.getTag();
        holder.text.setText(list.get(position).getName());
        //holder.btn.setChecked(list.get(position).isSelected());
        return view;
    }

    @Override
    public int getCount()
    {
        return list.size();
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public Model getItem(int position) {
        return (null==list)? null: list.get(position);
    }


}

模型类代码:

public class Model 
{
    private String name;

    public Model(String name) {
    this.name = name;

    }

    public String getName() {
    return name;
    }

    public void setName(String name) {
    this.name = name;
    }
}

对此有任何帮助都很棒。

3 个答案:

答案 0 :(得分:1)

就像我读到的那样,你正在用OnClickListener中使用的最终位置给视图充气

public View getView(final int position, View convertView, ViewGroup parent)

现在你通过删除一些项目来更改你的列表,虽然你的列表也被声明为final,但它可以被更改,因为它是我们可变的

private final List<Model> list;

所以你的名单正在改变,你的位置在足够删除后指向列表之外的某个地方

pseudocode
(1,2,3,4,5,6) with position = 4
delete(6)
delete(1)
delete(2)
results in (2,4,5)
now position 4 is pointing somewhere outside

答案 1 :(得分:1)

取消注释以下行

    //((ViewHolder) view.getTag()).text.setTag(list.get(position));

将remove语句替换为以下语句。

    list.remove(viewHolder.btn.getTag());

答案 2 :(得分:0)

使用以下代码更改适配器

public class InteractiveArrayAdapter extends ArrayAdapter<Model> {

  private final List<Model> list;
  private final Activity context; 
  private MainActivity ma;

 LayoutInflater inflator;
  public InteractiveArrayAdapter(Activity context, List<Model> list)
  {
    super(context, R.layout.rowbuttonlayout, list);
    this.context = context;
    inflator =  context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);;
  }

  static class ViewHolder
  {
    protected TextView text;
    protected Button btn;
  }

  @Override
  public View getView(final int position, View convertView, ViewGroup parent) {
    ViewHolder viewHolder;
    if (convertView == null) 
    {    
      convertView = inflator.inflate(R.layout.rowbuttonlayout, null);
      viewHolder = new ViewHolder();

      viewHolder.text = (TextView) view.findViewById(R.id.label);
      viewHolder.btn = (Button) view.findViewById(R.id.button1);     
      convertView.setTag(viewHolder);
      }

    else 
    {
        viewHolder = (ViewHolder)convertView.getTag();
     }
    viewHolder.btn.setOnClickListener(new OnClickListener()
      {
            public void onClick(View v)
            {       
            list.remove(position);
                    notifyDataSetChanged();  

            }

      });

   viewHolder.text.setText(list.get(position).getName());
   return convertView;
  }

  @Override
  public int getCount()
  {
      return list.size();
  }

  @Override
  public long getItemId(int position) {
        return position;
    }

  @Override
  public Object getItem(int position) {
      return list.get(position);
  }