我尝试刷新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?
答案 0 :(得分:83)
您可以使用RecyclerView.Adapter类中的notifyItemChanged(int position)
方法。来自文档:
通知任何注册观察员该位置的项目已更改。 相当于调用notifyItemChanged(position,null);。
这是项目更改事件,而不是结构更改事件。它 表示位置数据的任何反映都已过时 并应该更新。位置上的项目保持相同的身份。
由于你已经拥有这个职位,它应该适合你。
答案 1 :(得分:26)
notifyItemChanged(updateIndex)
改变"绵羊"项目,因此它说"我喜欢绵羊。"
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