在Android中使用notifyItemRemoved或notifyDataSetChanged与RecyclerView

我正在创build一个使用RecyclerView显示的卡片列表,其中每张卡片都有一个button来从列表中删除该卡片。

当我使用notifyItemRemoved()删除RecyclerView中的卡时,它删除项目和animation罚款,但列表中的数据不正确更新。

如果不是这样,我切换到notifyDataSetChanged()然后列表中的项目被删除并正确更新,但然后卡不animation。

有没有人有使用notifyItemRemoved()的经验,知道为什么它的行为不同于notifyDataSetChanged?

以下是我正在使用的一些代码:

private List<DetectedIssue> issues = new ArrayList<DetectedIssue>(); @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { // - get element from your dataset at this position // - replace the contents of the view with that element if(position >0){ RiskViewHolder riskHolder = (RiskViewHolder)holder; final int index = position - 1; final DetectedIssue anIssue = issues.get(index); riskHolder.button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { try { int index = issues.indexOf(anIssue); issues.remove(anIssue); notifyItemRemoved(index); //notifyDataSetChanged(); } catch (SQLException e) { e.printStackTrace(); } } }); } } @Override public int getItemCount() { return (issues.size()+1); } 

使用notifyItemRangeChanged(position,getItemCount()); notifyItemRemoved(position)之后;
你不需要使用索引,只是使用位置。 看下面的代码。

 private List<DetectedIssue> issues = new ArrayList<DetectedIssue>(); @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { // - get element from your dataset at this position // - replace the contents of the view with that element if(position >0){ RiskViewHolder riskHolder = (RiskViewHolder)holder; riskHolder.button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { try { issues.remove(position); notifyItemRemoved(position); //this line below gives you the animation and also updates the //list items after the deleted item notifyItemRangeChanged(position, getItemCount()); } catch (SQLException e) { e.printStackTrace(); } } }); } } @Override public int getItemCount() { return issues.size(); } 

试着

 public void removeItem(int position) { this.taskLists.remove(position); notifyItemRemoved(position); notifyItemRangeChanged(position, getItemCount() - position); } 

并像魅力一样工作。

我的错误, notifyItemChanged(position)是无奈的,位置的项目可以被移除,位置+ 1的项目是罚款,但项目从位置+2开始,你会得到一个exception,请使用notifyItemRangeChanged(position,getItemCount ()); notifyItemRemoved(position)之后;

喜欢这个:

 public void removeData(int position) { yourdatalist.remove(position); notifyItemRemoved(position); notifyItemRangeChanged(position,getItemCount()); } 

作为@pskinkbuild议它应该是(index + 1)在我的情况下notifyItemRemoved(index+1) ,可能是因为我保留顶部索引,即position=0的头。

您可以使用RecyclerView.ViewHolder getLayoutPosition()

getLayoutPosition()在布局和代码中提供项目的确切位置

 holder.removeButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //Position for remove int modPosition= holder.getLayoutPosition(); //remove item from dataset numbers.remove(modPosition); //remove item from recycler view notifyItemRemoved(modPosition); } }); 
 **my solution looks like this** this way is unnecessary to use the heavy method: //notifyItemRangeChanged(xx,xx) /** * * recyclerView的item中的某一个view,获取其最外层的viewParent,也就是item对应的layout在adapter中的position * * @param recyclerView * @param view:can be the deep one inside the item,or the item itself . * @return */ public static int getParentAdapterPosition(RecyclerView recyclerView, View view, int parentId) { if (view.getId() == parentId) return recyclerView.getChildAdapterPosition(view); View viewGroup = (View) view.getParent(); if (viewGroup != null && viewGroup.getId() == parentId) { return recyclerView.getChildAdapterPosition(viewGroup); } //recursion return getParentAdapterPosition(recyclerView, viewGroup, parentId); } //wherever you set the clickListener . holder.setOnClickListener(R.id.rLayout_device_item, deviceItemClickListener); holder.setOnLongClickListener(R.id.rLayout_device_item, deviceItemLongClickListener); @Override public boolean onLongClick(View v) { final int position = ViewUtils.getParentAdapterPosition(rVDevicesList, v, R.id.rLayout_device_item); return true; } 

您应该在ViewHolder类中添加删除侦听器

  button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { onCancel(getAdapterPosition()); } }); private void onCancel(int position) { if (position >= issues.size()) return; issues.remove(position); notifyItemRemoved(position); }