如何更新/刷新回收视图中的特定项目

我正在刷新 RecyclerView中的特定项目。

故事: 每当用户点击项目,它就显示 AlertDialog。用户可以通过点击确定按钮键入一些文本。我想在这个项目中显示这个文本,并显示不可见的 ImageView-声明在 XML 和适配器 ViewHolder-

我使用这个功能在 AlertDialog积极按钮更新项目:

private void updateListItem(int position) {
View view = layoutManager.findViewByPosition(position);
ImageView medicineSelected = (ImageView) view.findViewById(R.id.medicine_selected);
medicineSelected.setVisibility(View.VISIBLE);
TextView orderQuantity = (TextView) view.findViewById(R.id.order_quantity);
orderQuantity.setVisibility(View.VISIBLE);
orderQuantity.setText(quantity + " packet added!");


medicinesArrayAdapter.notifyItemChanged(position);
}

但是这段代码不仅改变了传递位置的 itemView,还改变了其他一些 itemView!

如何通过单击正确地更改特定的 itemView?

258263 次浏览

您可以使用回收视图.Adapter 类中的 notifyItemChanged(int position)方法:

通知任何已登记的观察员位置上的项目已发生变化。 等效于调用 notifyItemChanged (position,null) ; 。

这是一个项目更改事件,而不是结构更改事件 指示位置处的任何数据反射都已过期 并且应该更新。位置上的项目保持相同的标识。

既然你已经有了这个职位,它应该适合你。

我想我有办法了。更新与在确切位置进行删除和替换相同。因此,我首先使用下面的代码从该位置移除该项目:

public void removeItem(int position){
mData.remove(position);
notifyItemRemoved(position);
notifyItemRangeChanged(position, mData.size());
}

然后我会在这个特定的位置添加这个项目,如下所示:

public void addItem(int position, Landscape landscape){
mData.add(position, landscape);
notifyItemInserted(position);
notifyItemRangeChanged(position, mData.size());
}

我现在正在努力实现这个目标。当我完成的时候,我会给你一个反馈!

我通过捕捉需要修改的项目的位置来解决这个问题 然后在适配器调用中

public void refreshBlockOverlay(int position) {
notifyItemChanged(position);
}

,这将调用 BindViewHolder (ViewHolder,int 位置)为此特定项目在此特定位置。

这也是我最后一个问题,这是我的解决方案 我将数据模型和适配器用于我的回收视图

 /*Firstly, register your new data to your model*/
DataModel detail = new DataModel(id, name, sat, image);


/*after that, use set to replace old value with the new one*/
int index = 4;
mData.set(index, detail);


/*finally, refresh your adapter*/
if(adapter!=null)
adapter.notifyItemChanged(index);

更新单个项目

  1. 更新数据项
  2. notifyItemChanged(updateIndex)通知适配器更改

例子

更改“绵羊”项目,以便它说: “我喜欢绵羊。”

Update single item

String newValue = "I like sheep.";
int updateIndex = 3;
data.set(updateIndex, newValue);
adapter.notifyItemChanged(updateIndex);

我的完整答案与更多的例子是 给你

对我个人而言,一种有效的方法是使用回收视图的适配器方法来处理项目中的更改。

它将以类似的方式进行,在自定义回收者的视图中创建一个方法,有点像下面这样:

public void modifyItem(final int position, final Model model) {
mainModel.set(position, model);
notifyItemChanged(position);
}

下面的解决方案对我很有效:

在回收视图项上,用户将单击一个按钮,但另一个视图(如 TextView)将更新,而不会直接通知适配器:

我发现了一个不使用 notifyDataSetChanged ()方法的解决方案,这个方法重新加载所有回收视图的数据,所以如果你有图片或视频内容,那么他们将重新加载和用户体验将不好:

下面是一个例子,点击一个类似 ImageView 的图标,只更新一个文本视图(可能更新更多视图的相同方式相同的项目) ,以显示类似计数更新后添加 + 1:

// View holder class inside adapter class
public class MyViewHolder extends RecyclerView.ViewHolder{


ImageView imageViewLike;


public MyViewHolder(View itemView) {
super(itemView);


imageViewLike = itemView.findViewById(R.id.imageViewLike);
imageViewLike.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int pos = getAdapterPosition(); // Get clicked item position
TextView tv = v.getRootView().findViewById(R.id.textViewLikeCount); // Find textView of recyclerView item
resultList.get(pos).setLike(resultList.get(pos).getLike() + 1); // Need to change data list to show updated data again after scrolling
tv.setText(String.valueOf(resultList.get(pos).getLike())); // Set data to TextView from updated list
}
});
}

您只需要在保存时单击警告对话框中添加以下代码

          recyclerData.add(position, updateText.getText().toString());
recyclerAdapter.notifyItemChanged(position);

将更改后的文本添加到模型数据列表中

mdata.get(position).setSuborderStatusId("5");
mdata.get(position).setSuborderStatus("cancelled");
notifyItemChanged(position);

如果要创建一个对象并将其添加到适配器中使用的列表中, 当您在适配器中更改列表中的一个元素时,所有其他项也都会更改 换句话说,它完全是关于引用的,并且您的列表不包含单个对象的单独副本。

问题是 RecyclerView.Adatper没有提供任何返回元素索引的方法

public abstract static class Adapter<VH extends ViewHolder> {
/**
* returns index of the given element in adapter, return -1 if not exist
*/
public int indexOf(Object elem);
}

我的工作区是为(元素,位置) s 创建一个映射实例

public class FriendAdapter extends RecyclerView.Adapter<MyViewHolder> {
private Map<Friend, Integer> posMap ;
private List<Friend> friends;


public FriendAdapter(List<Friend> friends ) {
this.friends = new ArrayList<>(friends);
this.posMap = new HashMap<>();
for(int i = 0; i < this.friends.size(); i++) {
posMap.put(this.friends.get(i), i);
}
}


public int indexOf(Friend friend) {
Integer position = this.posMap.get(elem);
return position == null ? -1 : position;
}
// skip other methods in class Adapter
}
  • 元素类型(这里是类 Friend)应该实现 hashCode()equals(),因为它是散列表中的键。

当一个元素发生变化时,

  void someMethod() {
Friend friend = ...;
friend.setPhoneNumber('xxxxx');


int position = friendAdapter.indexOf(friend);
friendAdapter.notifyItemChanged(position);


}

最好定义一个助手方法

public class FriendAdapter extends extends RecyclerView.Adapter<MyViewHolder> {


public void friendUpdated(Friend friend) {
int position = this.indexOf(friend);
this.notifyItemChanged(position);
}
}

不一定需要映射实例(Map<Friend, Integer> posMap)。 如果不使用 map,则在整个列表中循环可以找到元素的位置。

我尝试了这种方法,它对我很有效:

private void updateItem(Object item, int position, int itemValue){
item.setItemNumber(itemValue) // update item field
notifyItemChanged(position, item);
}

确保传入要更新或刷新的项的对象、其在列表中的位置和值。

NotifYItemsChanged 将通知某个项目已更改,因此无论哪个项目已更改,都将更新所有列表。相反,您应该使用 DiffUtil。

点击这里阅读: https://developer.android.com/reference/androidx/recyclerview/widget/DiffUtil