问题
I would like two things :
- To not reload / refresh the adapter when i delete an item inside RecyclerView (no use of
notifyDatasetChanged
). - To do so i am using DiffUtils which works perfectly fine. But i also would like to keep the
DefaultItemAnimator
of theRecyclerView
which has apparently no effect with DiffUtils.
So my question is : How can i remove / update an item without refreshing all the dataset AND keep a similar animation to the DefaultItemAnimator
?
I know many posts gives answers about the RecyclerView
but none of them fit my needs.
I am aware of the notifyItemRemoved
, notifyItemRangeChanged
but they also refresh all the dataset.
Thanks
EDIT giving some code for a better understanding:
In my adapter i have made two methods : This is how i remove my view at the specific position.
// Adapter methods
void removeAt(int position) {
dataList.remove(position);
recyclerView.removeViewAt(position);
updateList(dataList);
}
void updateList(ArrayList<MyModel> newList) {
DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(new DiffUtilsTheme(oldList, newList));
diffResult.dispatchUpdatesTo(this);
}
And here is my DiffUtils class :
public class DiffUtils extends DiffUtil.Callback{
ArrayList<MyModel> oldItems;
ArrayList<MyModel> newItems;
public DiffUtils(ArrayList<MyModel> newItems, ArrayList<MyModel> oldItems) {
this.newItems = newItems;
this.oldItems = oldItems;
}
/**
* It returns the size of the old list.
* @return
*/
@Override
public int getOldListSize() {
return oldItems.size();
}
/**
* Returns the size of the new list;
* @return
*/
@Override
public int getNewListSize() {
return newItems.size();
}
/**
* Called by the DiffUtil to decide whether two object represent the same Item.
* Here we check the names because we know they are unique.
* @param oldItemPosition
* @param newItemPosition
* @return
*/
@Override
public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
// We are sure that the names are unique
return oldItems.get(oldItemPosition).getItemName().equals(newItem.get(newItemPosition).getItemName());
}
/**
* Checks whether two items have the same data.
* This method is called by DiffUtil only if areItemsTheSame returns true.
* @param oldItemPosition
* @param newItemPosition
* @return
*/
@Override
public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
return oldItems.get(oldItemPosition).equals(newItems.get(newItemPosition));
}
/**
* If areItemTheSame return true and areContentsTheSame returns false DiffUtil calls this method to get a payload about the change.
* @param oldItemPosition
* @param newItemPosition
* @return
*/
@Nullable
@Override
public Object getChangePayload(int oldItemPosition, int newItemPosition) {
return super.getChangePayload(oldItemPosition, newItemPosition);
}
}
This removes perfectly the item from the list but without animation.
My RecyclerView
has also the ItemAnimator
:
recyclerView.setItemAnimator(new DefaultItemAnimator());
Before using the DiffUtils
class, i was removing like this :
void removeAt(int position) {
dataList.remove(position);
notifyItemRemoved(position);
notifyItemRangeChanged(position, dataList.size());
}
Which was also working and with an animation, but was refreshing all the other items.
来源:https://stackoverflow.com/questions/60905423/recyclerview-diffutils-animation-when-dataset-change-without-full-refresh