Created
March 24, 2015 02:32
-
-
Save boxme/92ef8bd391ed55e00b9b to your computer and use it in GitHub Desktop.
CursorRecyclerView
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
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