Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Cursor Diff Util callback.
import android.database.Cursor;
import android.support.annotation.Nullable;
import android.support.v7.util.DiffUtil;
/**
* Created by Nikola on 9/29/2016.
*/
public abstract class CursorCallback<C extends Cursor> extends DiffUtil.Callback {
private final C newCursor;
private final C oldCursor;
public CursorCallback(C newCursor, C oldCursor) {
this.newCursor = newCursor;
this.oldCursor = oldCursor;
}
@Override
public int getOldListSize() {
return oldCursor == null ? 0 : oldCursor.getCount();
}
@Override
public int getNewListSize() {
return newCursor == null? 0 : newCursor.getCount();
}
@Override
public final boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
return oldCursor.getColumnCount() == newCursor.getColumnCount() && moveCursorsToPosition(oldItemPosition, newItemPosition) && areCursorRowsTheSame(oldCursor, newCursor);
}
@Override
public final boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
return oldCursor.getColumnCount() == newCursor.getColumnCount() && moveCursorsToPosition(oldItemPosition, newItemPosition) && areRowContentsTheSame(oldCursor, newCursor);
}
@Nullable
@Override
public final Object getChangePayload(int oldItemPosition, int newItemPosition) {
moveCursorsToPosition(oldItemPosition, newItemPosition);
return getChangePayload(newCursor, oldCursor);
}
@Nullable
public Object getChangePayload(C newCursor, C oldCursor) {
return null;
}
private boolean moveCursorsToPosition(int oldItemPosition, int newItemPosition) {
boolean newMoved = newCursor.moveToPosition(newItemPosition);
boolean oldMoved = oldCursor.moveToPosition(oldItemPosition);
return newMoved && oldMoved;
}
/** Cursors are already moved to positions where you should obtain data by row.
* Checks if contents at row are same
*
* @param oldCursor Old cursor object
* @param newCursor New cursor object
* @return See DiffUtil
*/
public abstract boolean areRowContentsTheSame(Cursor oldCursor, Cursor newCursor);
/** Cursors are already moved to positions where you should obtain data from row
* Checks if rows are the same, ideally, check by unique id
* @param oldCursor Old cursor object
* @param newCursor New cursor object
* @return See DiffUtil
*/
public abstract boolean areCursorRowsTheSame(Cursor oldCursor, Cursor newCursor);
}
@LouisCAD
Copy link

LouisCAD commented Oct 5, 2016

Hi, a sample using this code would be nice so we can test it before integrating it in our projects

@cbeyls
Copy link

cbeyls commented Feb 17, 2017

Please, avoid using DiffUtil in combination with any Cursor (except for MatrixCursor). Even Yigit Boyar (the author of DiffUtil) says it. Cursors like SQLiteCursor load their data lazily while DiffUtil require instant random access to every possible item from first to last, so you need the entire data set loaded into memory first. If your Cursor comes from SQLite, it's recommended to transfer its data to an ArrayList first before passing it to DiffUtil, or not use DiffUtil in that case.

@cbeyls
Copy link

cbeyls commented Feb 17, 2017

Also I find it odd that you pass the new cursor as first argument and old cursor as second argument in the constructor while in all other methods it's always old first and new second.

@omerjerk
Copy link

omerjerk commented Jan 18, 2018

^^ Agreed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment