【问题标题】:IndexOutofBound error while deleting item from ListView从 ListView 中删除项目时出现 IndexOutofBound 错误
【发布时间】:2017-12-15 14:31:21
【问题描述】:

我已经搜索了几乎所有与此主题相关的可能问题,但无法解决此问题。每当我尝试通过嵌入 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;
    }
}

任何有关这方面的帮助都会很棒。

【问题讨论】:

    标签: android listview


    【解决方案1】:

    取消注释以下行

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

    将您的删除语句替换为以下语句。

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

    【讨论】:

    • 它几乎成功了,但是当列表中剩下 3 个项目时,删除项目会停止...这里可能有什么问题?
    • 事实上它是以非常随机的顺序删除..单击其他项目时会删除另一个项目..奇怪..
    • 我需要做的就是替换这个“list.remove(position);”用你的行“list.remove(viewHolder.btn.getTag());”..你是救生员..谢谢!!
    【解决方案2】:

    正如我所读到的那样,您正在使用 OnClickListener 中使用的最终位置夸大您的视图

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

    现在您通过删除一些项目来更改您的列表,虽然您的列表也声明为最终列表,但它可以更改,因为它是可变的

    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
    

    【讨论】:

    • 是的,你是对的。但有些我无法通过代码弄清楚。
    • 也许您可以切换到 HashMap 并将字符串传递给侦听器,以便它会删除正确的条目。然后完成后,您可以遍历 Map 中留下的键以执行进一步的逻辑。
    【解决方案3】:

    使用以下代码更改您的适配器

    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);
      }
    

    【讨论】:

    • 你需要看看如何为listview创建自定义适配器。
    猜你喜欢
    • 2018-01-31
    • 1970-01-01
    • 1970-01-01
    • 2016-09-24
    • 2016-03-20
    • 1970-01-01
    • 2017-03-08
    • 2014-08-16
    • 1970-01-01
    相关资源
    最近更新 更多