こんにちは @wasabeef_jpです。

RecyclerViewだとCursorAdapterは使えないので
CursorAdapterを参考に、RecyclerView用のAbstractクラスを作ったので
ブログに残しておきます。

public abstract class AbstractCursorRecycleAdapter<VH extends RecyclerView.ViewHolder>  
        extends RecyclerView.Adapter<VH> {

    @NonNull
    protected Cursor mCursor;
    protected boolean mDataValid;
    protected int mRowIDColumn;

    protected ChangeObserver mChangeObserver;
    protected DataSetObserver mDataSetObserver;

    public AbstractCursorRecycleAdapter(@NonNull Cursor c) {
        mCursor = c;
        mDataValid = true;
        mRowIDColumn = c.getColumnIndexOrThrow(MediaStore.Images.Media._ID);

        mChangeObserver = new ChangeObserver();
        mCursor.registerContentObserver(mChangeObserver);

        mDataSetObserver = new CursorDataSetObserver();
        mCursor.registerDataSetObserver(mDataSetObserver);

        setHasStableIds(true);
    }

    @Override
    public int getItemCount() {
        if (mDataValid) {
            return mCursor.getCount();
        } else {
            return 0;
        }
    }

    @Override
    public long getItemId(int position) {
        if (!mDataValid) {
            return 0;
        }

        if (mCursor.moveToPosition(position)) {
            return mCursor.getLong(mRowIDColumn);
        } else {
            return 0;
        }
    }

    public abstract void onBindViewHolder(VH holder, Cursor cursor);

    @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(@NonNull Cursor cursor) {
        Cursor old = swapCursor(cursor);
        if (old != null) {
            old.close();
        }
    }

    private Cursor swapCursor(@NonNull Cursor newCursor) {
        if (newCursor == mCursor) {
            return null;
        }
        Cursor oldCursor = mCursor;
        oldCursor.unregisterContentObserver(mChangeObserver);
        oldCursor.unregisterDataSetObserver(mDataSetObserver);

        mCursor = newCursor;
        newCursor.registerContentObserver(mChangeObserver);
        newCursor.registerDataSetObserver(mDataSetObserver);

        mRowIDColumn = newCursor.getColumnIndexOrThrow(MediaStore.Images.Media._ID);
        mDataValid = true;
        notifyDataSetChanged();

        return oldCursor;
    }

    protected abstract void onContentChanged();

    private class ChangeObserver extends ContentObserver {

        public ChangeObserver() {
            super(new Handler());
        }

        @Override
        public boolean deliverSelfNotifications() {
            return true;
        }

        @Override
        public void onChange(boolean selfChange) {
            onContentChanged();
        }
    }

    private class CursorDataSetObserver extends DataSetObserver {

        @Override
        public void onChanged() {
            mDataValid = true;
            notifyDataSetChanged();
        }

        @Override
        public void onInvalidated() {
            mDataValid = false;
            notifyDataSetChanged();
        }
    }
}