Skip to content

Instantly share code, notes, and snippets.

@boxme
Created March 24, 2015 02:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save boxme/92ef8bd391ed55e00b9b to your computer and use it in GitHub Desktop.
Save boxme/92ef8bd391ed55e00b9b to your computer and use it in GitHub Desktop.
CursorRecyclerView
public abstract class AbstractCursorRecyclerAdapter<VH extends RecyclerView.ViewHolder>
extends RecyclerView.Adapter<VH> {
protected Context mContext;
protected Cursor mCursor;
protected boolean mDataValid;
protected int mRowIDColumn;
protected ChangeObserver mChangeObserver;
protected DataSetObserver mDataSetObserver;
public abstract void onBindViewHolder(VH holder, Cursor cursor);
public abstract void changeDataSet();
public interface ItemClickListener {
void itemClicked(int id);
}
public AbstractCursorRecyclerAdapter(Context context, Cursor cursor) {
boolean cursorPresent = cursor != null;
mCursor = cursor;
mDataValid = cursorPresent;
mContext = context;
mRowIDColumn = cursorPresent ? cursor.getColumnIndexOrThrow("_id") : -1;
if (cursorPresent) {
mChangeObserver = new ChangeObserver();
mDataSetObserver = new CursorDataSetObserver();
cursor.registerContentObserver(mChangeObserver);
cursor.registerDataSetObserver(mDataSetObserver);
}
setHasStableIds(true);
}
@Override
public int getItemCount() {
if (mDataValid) {
return mCursor.getCount();
}
return 0;
}
@Override
public long getItemId(int position) {
if (!mDataValid) {
return 0;
}
if (mCursor.moveToPosition(position)) {
return mCursor.getLong(mRowIDColumn);
}
return 0;
}
public Object getItem(int position) {
if (mDataValid && mCursor != null) {
mCursor.moveToPosition(position);
return mCursor;
} else {
return null;
}
}
@Override
public void onBindViewHolder(VH holder, int position) {
if (!mDataValid) {
throw new IllegalStateException("this should only be called when the cursor is valid");
}
if (!mCursor.moveToPosition(position)) {
throw new IllegalStateException("couldn't move cursor to position " + position);
}
onBindViewHolder(holder, mCursor);
}
public void changeCursor(Cursor cursor) {
Cursor old = swapCursor(cursor);
if (old != null) {
old.close();
}
}
public Cursor swapCursor(Cursor newCursor) {
if (newCursor == mCursor) {
return null;
}
Cursor oldCursor = mCursor;
if (oldCursor != null) {
if (mChangeObserver != null) oldCursor.unregisterContentObserver(mChangeObserver);
if (mDataSetObserver != null) oldCursor.unregisterDataSetObserver(mDataSetObserver);
}
mCursor = newCursor;
if (newCursor != null) {
if (mChangeObserver != null) newCursor.registerContentObserver(mChangeObserver);
if (mDataSetObserver != null) newCursor.registerDataSetObserver(mDataSetObserver);
mRowIDColumn = newCursor.getColumnIndexOrThrow("_id");
mDataValid = true;
// notify the observers about the new cursor
changeDataSet();
} else {
mRowIDColumn = -1;
mDataValid = false;
}
notifyDataSetChanged();
return oldCursor;
}
protected void onContentChange() {
if (mCursor != null && !mCursor.isClosed()) {
mDataValid = mCursor.requery();
}
}
/**
* ContentObserver is used to watch for changes in underlying data.
* ContentObserver#onChange(boolean) will be called when a change occurs
*
*
*/
private class ChangeObserver extends ContentObserver {
public ChangeObserver() {
super(new Handler());
}
@Override
public void onChange(boolean selfChange) {
onContentChange();
}
@Override
public boolean deliverSelfNotifications() {
return true;
}
}
/**
* DataSetObserver is notified of cursor lifecycle changes such as closing and re-querying
*/
private class CursorDataSetObserver extends DataSetObserver {
@Override
public void onChanged() {
mDataValid = true;
notifyDataSetChanged();
}
@Override
public void onInvalidated() {
mDataValid = false;
notifyDataSetChanged();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment