如何使用 DiffUtil 更新 RecyclerView 适配器
Posted
技术标签:
【中文标题】如何使用 DiffUtil 更新 RecyclerView 适配器【英文标题】:How to update RecyclerView adapter using DiffUtil 【发布时间】:2018-03-17 14:58:19 【问题描述】:每次我需要更新 RecycleView 中的警报时,我都会创建一个新的 Adapter 和一个新的 RecycleView。不幸的是,它只是一个非常昂贵的“解决方案”。我在网上看到我可以使用 DiffUti,但我不知道如何实现它。 我创建了一个 DiffUtil 类:
public class AlarmDiffCallBack extends DiffUtil.Callback
private final ArrayList<SingleAlarm> oldList;
private final ArrayList<SingleAlarm> newList;
public AlarmDiffCallBack( ArrayList<SingleAlarm> oldList, ArrayList<SingleAlarm> newList)
this.oldList = oldList;
this.newList = newList;
@Override
public int getOldListSize()
return oldList.size();
@Override
public int getNewListSize()
return newList.size();
@Override
public boolean areItemsTheSame(int oldItemPosition, int newItemPosition)
return oldList.get(oldItemPosition).getAlarmIndex() == newList.get(newItemPosition).getAlarmIndex();
@Override
public boolean areContentsTheSame(int oldItemPosition, int newItemPosition)
return oldList.get(oldItemPosition).getAlarmIndex() == newList.get(newItemPosition).getAlarmIndex();
@Nullable
@Override
public Object getChangePayload(int oldItemPosition, int newItemPosition)
// Implement method if you're going to use ItemAnimator
return super.getChangePayload(oldItemPosition, newItemPosition);
这是我要更新recycleView的地方之一(用DiffUtil替换“creatAdapter”):
public void add_alarm(final Context context)
//creating a new alarm and set the relevant varible to the addAlarm function
button_add_alarm.setOnClickListener(new View.OnClickListener()
public void onClick(View v)
//the calndar is without the right day, the day is added in the handler(int the loop)
Calendar calendarForAlarm = timePickerToCalendar(alarmTimePicker);
alarmsList = alarmHandler.add_alarm(context, checkBoxes, alarmMessage, alarmsList, alarm_manager, calendarForAlarm, repeatAlarm);
alarmsList=alarmHandler.sortAlarms(alarmsList);
creatAdapt();
);
我只是不知道如何使用这个类来更新我的适配器。我对 android 和一般编程很陌生,希望这个报价没问题。谢谢!
【问题讨论】:
【参考方案1】:您的 areItemsTheSame 和 areContentsTheSame 方法是相同的。
getChangePayload 只有在 areItemsTheSame 返回 true 并且 areContentsTheSame 返回 false 时才会触发,所以我认为它永远不会触发
【讨论】:
【参考方案2】:所以基本上你需要你的适配器有一个方法来更新你的数据,就像这样:
public void setNewAlarms(List<SingleAlarm> newAlarms)
// oldAlarms is the list of items currently displayed by the adapter
AlarmDiffCallBack diffCallBack = new AlarmDiffCallBack(oldAlarms, newAlarms);
// Second parameter is to detect "movement". If your list is always sorted the same way, you can set it to false to optimize
DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(diffCallBack, true);
// This will notify the adapter of what is new data, and will animate/update it for you ("this" being the adapter)
diffResult.dispatchUpdatesTo(this);
然后您只需从适配器外部调用 myAdapater.setNewAlarms(alarmsList)
并使用新数据。
你也可以看看实现它的following repository
【讨论】:
你帮助我更接近解决方案,但它仍然对我不起作用。首先,我看到在你的存储库中你手动更新了你的列表(list.clear(); list .addall(); - 即使我操作了 diffResult.dispatchUpdatesTo(this),我是否应该添加那些列表?另外,有没有这些功能,它只是更新了我的 RecyclerView,也许我的 AlarmDiffCallBack 磨损了?非常感谢!跨度>以上是关于如何使用 DiffUtil 更新 RecyclerView 适配器的主要内容,如果未能解决你的问题,请参考以下文章
当视图更新 Android Kotlin 时,DiffUtil 不与 ListAdpater 一起使用
DiffUtil 不刷新观察者调用android kotlin中的视图