Cursor Diff Util callback.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | |
} |
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.
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.
^^ Agreed.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi, a sample using this code would be nice so we can test it before integrating it in our projects