Skip to content

Instantly share code, notes, and snippets.

@NikolaDespotoski
Last active March 21, 2020 05:11
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save NikolaDespotoski/9e4f76c58264ffaf5e9f1eb6096b07ba to your computer and use it in GitHub Desktop.
Save NikolaDespotoski/9e4f76c58264ffaf5e9f1eb6096b07ba to your computer and use it in GitHub Desktop.
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);
}
@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

^^ Agreed.

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