2017-01-30 74 views
0

我有一个arraylist,我正在使用ImageButton从列表中删除项目。如果我从相同的位置删除3个项目,则应用程序会崩溃并显示IndexOutOfBoundsException。我不知道如何在删除项目之前更改项目的数组位置。java.lang.IndexOutOfBoundsException:索引无效

@Override 
public void onBindViewHolder(MyViewHolder holder, final int position) { 
    ExRow expense = expenseList.get(position); 
    holder.title.setText(expense.getTitle()); 
    holder.amount.setText(expense.getAmount()); 
    mRemoveButton.setOnClickListener(new View.OnClickListener() { 

     public void onClick(View view) { 
      // Remove the item on remove/button click 
      expenseList.remove(position); 
      notifyItemRemoved(position); 
      notifyItemRangeChanged(position, expenseList.size()); 

     } 
    }); 
} 
+0

你为什么要叫两个'notifyItemRemoved()'和'notifyItemRangeChanged()'?只有一个应该足够了 –

+0

你可以添加异常的堆栈跟踪并使你的代码示例更完整吗?例如,它完全不清楚“费用列表”是什么对象。 – dpr

+0

尝试用'ExRow expense = expenseList.get(holder.getAdapterPosition());' –

回答

1

有很多可能的解决方案。

这一个根据我的理想

@Override 
public void onBindViewHolder(final MyViewHolder holder, int position) { 
    ExRow expense = expenseList.get(holder.getAdapterPosition()); 
    holder.title.setText(expense.getTitle()); 
    holder.amount.setText(expense.getAmount()); 
    mRemoveButton.setOnClickListener(new View.OnClickListener() { 
     public void onClick(View view) { 
      // Remove the item on remove/button click 
      int adapterPosition = holder.getAdapterPosition(); 
      expenseList.remove(adapterPosition); 
      notifyItemRemoved(adapterPosition); 
      notifyDatasetChanged(); 
     } 
    }); 
} 
+0

谢谢你完美的工作!你能解释一下吗,这样我就可以确定我明白了吗? – Corpse

+0

在我的博客http://blog.inapptext.com/recyclerview-creating-dynamic-lists-and-grids-in-android-1/#common_mistakes的这部分我已经提到了LayoutPosition和AdapterPosition之间的区别。一旦你的差异,你可以理解,即使从列表中删除n项,你使用的作为最终变量的LayoutPosition保持不变。但使用持有人的adapterPosition将永远给你持有人在列表中的当前位置。 –

+0

谢谢。这对我帮助很大。 – Corpse

1

ArrayList,当从一个索引中删除的元素,各元素的索引之后被移位到左侧。举个例子:

Index | Value 
0  A 
1  B 
2  C 
3  D 

当你从数组中删除索引2,这里的结果:

Index | Value 
0  A 
1  B 
2  D 

所以我的猜测是:你是从你的清单,在某些时候,position删除索引position仅比列表中元素的数量高。

更新: 下面的解决方案的一些灵感。如果不理解用例,很难找到一个好的解决方案。

public void onClick(View view) { 
     // Remove the item on remove/button click 
     if(position >= expenseList.size()) return; 
     expenseList.remove(position); 
     notifyItemRemoved(position); 
     notifyItemRangeChanged(position, expenseList.size()); 
    } 

或者:

public void onClick(View view) { 
     // Remove the item on remove/button click 
     if(expenseList.size() == 0) return; 
     if(position >= expenseList.size()) { 
      position = expenseList.size() -1; 
     } 
     expenseList.remove(position); 
     notifyItemRemoved(position); 
     notifyItemRangeChanged(position, expenseList.size()); 
    } 

等。

+0

替换ExRow费用= expenseList.get(position);'我如何解决这个问题? – Corpse

+0

您可以检查ArrayList的长度是否大于位置。或者您使用迭代器从列表中删除项目。或者你正确计算位置。 – fjc

+0

不确定这是否正常工作,但arraylist具有可用于获取对象位置的indexOf方法。尝试将其与删除结合起来。即mylist.remove(mylist.indexOf(myObject)); – Andy

0

删除该行 notifyItemRangeChanged(position,expenseList.size());

notifyItemRemoved(position);这足以从列表中删除项目。

+0

没有它不够。如果您阅读文档,notifyItemRemoved将不会更新资源。你必须手动处理它。 –

+0

可以放异常日志? –

0

使您的模型最终并用它来确定位置。

@Override 
public void onBindViewHolder(MyViewHolder holder, int position) { 
    final ExRow expense = expenseList.get(position); 
    holder.title.setText(expense.getTitle()); 
    holder.amount.setText(expense.getAmount()); 
    mRemoveButton.setOnClickListener(new View.OnClickListener() { 

     public void onClick(View view) { 
      // Remove the item on remove/button click 
      int pos = expenseList.indexOf(expense); 

      if (pos == -1) 
       return; 

      expenseList.remove(pos); 
      notifyItemRemoved(pos); 
      notifyItemRangeChanged(pos, expenseList.size()); 

     } 
    }); 
} 
相关问题