如何在RecyclerView中更新/刷新特定项目

时间:2015-09-08 12:05:43

标签: android android-recyclerview android-adapter recycler-adapter

我尝试刷新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?

14 个答案:

答案 0 :(得分:83)

您可以使用RecyclerView.Adapter类中的notifyItemChanged(int position)方法。来自文档:

  

通知任何注册观察员该位置的项目已更改。   相当于调用notifyItemChanged(position,null);。

     

这是项目更改事件,而不是结构更改事件。它   表示位置数据的任何反映都已过时   并应该更新。位置上的项目保持相同的身份。

由于你已经拥有这个职位,它应该适合你。

答案 1 :(得分:26)

更新单个项目

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

    实施例

    改变"绵羊"项目,因此它说"我喜欢绵羊。"

    Update single item

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

    我的完整答案包含更多示例here

答案 2 :(得分:8)

我想我对如何处理这个有一个想法。更新与在确切位置删除和替换相同。所以我首先使用下面的代码从该位置删除该项目:

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

我现在正试图实现这一点。我通过时会给你反馈意见!

答案 3 :(得分:7)

我必须通过捕获需要修改的项目的位置来解决此问题 然后在适配器调用中

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

,这将在此特定位置调用此特定项目的onBindViewHolder(ViewHolder holder,int position)。

答案 4 :(得分:4)

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

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

答案 5 :(得分:1)

一种对我个人有用的方法是使用recyclerview的适配器方法来处理其项目的变化。

它会以类似于此的方式,在您的自定义回收站的视图中创建一个方法,如下所示:

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

答案 6 :(得分:1)

以下解决方案对我有用:

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

我找到了一个很好的解决方案,而无需使用notifyDataSetChanged()方法,该方法将重新加载recyclerView的所有数据,因此,如果您在其中包含图像或视频,则它们将被重新加载,并且用户体验将不佳:

这里是单击像ImageView之类的图标并仅更新单个TextView(可以以相同的方式更新更多视图的示例),以在添加+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
            }
        });
    }

答案 7 :(得分:0)

在你的适配器类中,在onBindViewHolder方法中,将ViewHolder设置为setIsRecyclable(false),如下面的代码所示。

@Override
public void onBindViewHolder(RecyclerViewAdapter.ViewHolder p1, int p2)
{
    // TODO: Implement this method
    p1.setIsRecyclable(false);

    // Then your other codes
}

答案 8 :(得分:0)

您只需在保存对话框中的“警告”对话框中添加以下代码

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

答案 9 :(得分:0)

问题是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);
}

我的解决方法是为(元素,位置)创建地图实例

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,则遍历整个列表可以找到元素的位置。

答案 10 :(得分:0)

我试过了,它对我有用:

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

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

答案 11 :(得分:-1)

这也是我的最后一个问题。我的解决方案 我将数据模型和适配器用于我的RecyclerView

 /*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);

答案 12 :(得分:-1)

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

答案 13 :(得分:-5)

在您的RecyclerView适配器中,您应该有一个ArrayList和一个方法addItemsToList(items)来将列表项添加到ArrayList。然后,您可以动态调用adapter.addItemsToList(items)添加列表项。将所有列表项添加到ArrayList后,您可以调用adapter.notifyDataSetChanged()来显示列表。

您可以使用适配器中的notifyDataSetChanged进行RecyclerView