当我获得要分配给它的新列表时,如何在 RecyclerView 旧数据列表中正确通知 ItemMoved、插入和删除
How to properly notifyItemMoved, insert and removed in RecyclerView old data list when i get new fresh list to assign to it
我正在我的 RecyclerView 适配器中一次性填充新数据,因此没有插入或删除一项操作。
很简单,我有一个旧列表,当某些事件发生时,我会得到新列表,然后我可以将新列表分配给旧列表。
问题是我无法为旧列表中的每个项目正确制作动画
- 当项目在新列表中有新位置时(应该 notifyItemMoved 从旧位置到新位置)
- 当新列表中有新项目时(应该通知ItemInserted新列表中的那个位置)
- 当旧项目不在新列表中时(应在该位置通知 ItemRemoved)
这是我现在拥有的东西,我认为它适用于第一种情况 - 项目移动到新位置:
if(currentAdapterData!= null){
for(int i = 0; i < currentAdapterData.size(); i++){
for(int j = 0; j < newData.size(); j++){
if(currentAdapterData.get(i).getSomeIdentifier().equals(newData.get(j).getSomeIdentifier())){
Log.v("same item", "currentAdapterData index :" + i + " ," + currentAdapterData.get(i).getSomeIdentifier() + " == newData index: " + j + " ," + newData.get(j).getSomeIdentifier());
if(i != j){
notifyItemMoved(i, j);
}
}
}
}
}
currentAdapterData = newData;
但是它没有按预期工作,并且日志(正确)和出现在 phone 上的列表之间存在差异(项目位置错误、一些重复、错误等)
那么我怎样才能让它发挥作用呢?使用 notifyItemMoved、notifyItemInserted 和 notifyItemRemoved?
我不想只使用 NofifyDataSetChanged,因为它会刷新整个列表,而不是仅仅用已更改的动画更新项目。
看来你的新数据也是列表的形式,不是单项。我认为这可能是在支持库中使用 DiffUtil 的一个很好的候选者。
Here 也是一个很好的教程。
它将允许您计算新数据的差异并只更新需要的字段。它还将异步卸载工作。
您只需要实现一个 DiffUtil.Callback
来指示您的项目是否相同或内容是否相同。
你像这样更新你的 recyclerView:
DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(diffCallback);
diffResult.dispatchUpdatesTo(yourAdapter);
像这样使用DiffUtil就可以了
final MyDiffCallback diffCallback = new MyDiffCallback(prevList, newList);
final DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(diffCallback);
通过扩展 MyDiffCallback 和覆盖方法创建回调,并根据需要执行。
public class MyDiffCallback extends DiffUtil.Callback
// 覆盖方法
好吧,我觉得这是 easiest.Just 跟着它 ->
替换这个
if(currentAdapterData!= null){
for(int i = 0; i < currentAdapterData.size(); i++){
for(int j = 0; j < newData.size(); j++){
if(currentAdapterData.get(i).getSomeIdentifier().equals(newData.get(j).getSomeIdentifier())){
Log.v("same item", "currentAdapterData index :" + i + " ," + currentAdapterData.get(i).getSomeIdentifier() + " == newData index: " + j + " ," + newData.get(j).getSomeIdentifier());
if(i != j){
notifyItemMoved(i, j);
}
}
}
}
}
currentAdapterData = newData;
和
if(currentAdapterData!= null){
for(int i = 0; i < currentAdapterData.size(); i++){
for(int j = 0; j < newData.size(); j++){
if(currentAdapterData.get(i).getSomeIdentifier().equals(newData.get(j).getSomeIdentifier())){
Log.v("same item", "currentAdapterData index :" + i + " ," + currentAdapterData.get(i).getSomeIdentifier() + " == newData index: " + j + " ," + newData.get(j).getSomeIdentifier());
if(i != j){
notifyDataSetChanged();
new CountDownTimer(250, 250) {
@Override
public void onTick(long millisUntilFinished) {
Log.d("millisUntilFinished", "" + millisUntilFinished);
}
@Override
public void onFinish() {
notifyItemMoved(i, j);
}
}.start();
}
}
}
}
}
这将更新值并在 250 毫秒(1/4 秒)后,值随动画一起移动。
我正在我的 RecyclerView 适配器中一次性填充新数据,因此没有插入或删除一项操作。
很简单,我有一个旧列表,当某些事件发生时,我会得到新列表,然后我可以将新列表分配给旧列表。
问题是我无法为旧列表中的每个项目正确制作动画
- 当项目在新列表中有新位置时(应该 notifyItemMoved 从旧位置到新位置)
- 当新列表中有新项目时(应该通知ItemInserted新列表中的那个位置)
- 当旧项目不在新列表中时(应在该位置通知 ItemRemoved)
这是我现在拥有的东西,我认为它适用于第一种情况 - 项目移动到新位置:
if(currentAdapterData!= null){
for(int i = 0; i < currentAdapterData.size(); i++){
for(int j = 0; j < newData.size(); j++){
if(currentAdapterData.get(i).getSomeIdentifier().equals(newData.get(j).getSomeIdentifier())){
Log.v("same item", "currentAdapterData index :" + i + " ," + currentAdapterData.get(i).getSomeIdentifier() + " == newData index: " + j + " ," + newData.get(j).getSomeIdentifier());
if(i != j){
notifyItemMoved(i, j);
}
}
}
}
}
currentAdapterData = newData;
但是它没有按预期工作,并且日志(正确)和出现在 phone 上的列表之间存在差异(项目位置错误、一些重复、错误等)
那么我怎样才能让它发挥作用呢?使用 notifyItemMoved、notifyItemInserted 和 notifyItemRemoved?
我不想只使用 NofifyDataSetChanged,因为它会刷新整个列表,而不是仅仅用已更改的动画更新项目。
看来你的新数据也是列表的形式,不是单项。我认为这可能是在支持库中使用 DiffUtil 的一个很好的候选者。 Here 也是一个很好的教程。
它将允许您计算新数据的差异并只更新需要的字段。它还将异步卸载工作。
您只需要实现一个 DiffUtil.Callback
来指示您的项目是否相同或内容是否相同。
你像这样更新你的 recyclerView:
DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(diffCallback);
diffResult.dispatchUpdatesTo(yourAdapter);
像这样使用DiffUtil就可以了
final MyDiffCallback diffCallback = new MyDiffCallback(prevList, newList);
final DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(diffCallback);
通过扩展 MyDiffCallback 和覆盖方法创建回调,并根据需要执行。
public class MyDiffCallback extends DiffUtil.Callback
// 覆盖方法
好吧,我觉得这是 easiest.Just 跟着它 ->
替换这个
if(currentAdapterData!= null){
for(int i = 0; i < currentAdapterData.size(); i++){
for(int j = 0; j < newData.size(); j++){
if(currentAdapterData.get(i).getSomeIdentifier().equals(newData.get(j).getSomeIdentifier())){
Log.v("same item", "currentAdapterData index :" + i + " ," + currentAdapterData.get(i).getSomeIdentifier() + " == newData index: " + j + " ," + newData.get(j).getSomeIdentifier());
if(i != j){
notifyItemMoved(i, j);
}
}
}
}
}
currentAdapterData = newData;
和
if(currentAdapterData!= null){
for(int i = 0; i < currentAdapterData.size(); i++){
for(int j = 0; j < newData.size(); j++){
if(currentAdapterData.get(i).getSomeIdentifier().equals(newData.get(j).getSomeIdentifier())){
Log.v("same item", "currentAdapterData index :" + i + " ," + currentAdapterData.get(i).getSomeIdentifier() + " == newData index: " + j + " ," + newData.get(j).getSomeIdentifier());
if(i != j){
notifyDataSetChanged();
new CountDownTimer(250, 250) {
@Override
public void onTick(long millisUntilFinished) {
Log.d("millisUntilFinished", "" + millisUntilFinished);
}
@Override
public void onFinish() {
notifyItemMoved(i, j);
}
}.start();
}
}
}
}
}
这将更新值并在 250 毫秒(1/4 秒)后,值随动画一起移动。