Android不提供要与recyclerView一起使用的CursorAdapter。
我尝试过使用此处的CursorRecyclerViewAdapter: https://gist.github.com/skyfishjy/443b7448f59be978bc59
当我从ContentProvider调用notifyChange时, 观察者没有被调用。
~SNIP my Fragment / Controller ....
//adapter
mAdapter = new CursorRecyclerViewAdapter(getActivity(), null,true) {
@Override
public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, Cursor cursor) {
((WidgetAdapter.ViewHolder)viewHolder).setTitle(cursor.getString(4) + " id: " + cursor.getInt(0) + " order: " + cursor.getInt(15));
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
Context context = viewGroup.getContext();
View parent = LayoutInflater.from(context).inflate(R.layout.ned_apps_order_item, viewGroup, false);
return WidgetAdapter.ViewHolder.newInstance(parent);
}
};
mRecyclerView.setAdapter(mAdapter);
~SNIP - Loader CallBacks
@Override
public Loader<Cursor> onCreateLoader(int i, Bundle bundle) {
String parent_id = bundle == null ? "0" : "" + bundle.getInt(PARENT_ID);
String PARENT_SELECTION = PARENT_ID + "= ?";
return new CursorLoader(getActivity(), Schema.CONTENT_URI,null,
PARENT_SELECTION,new String[] {parent_id}, "_order ASC");
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
mAdapter.swapCursor(cursor);
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
mAdapter.swapCursor(null);
}
~SNIP
~SNIP~ my Provider.....
@Override
public int update(Uri uri, ContentValues contentValues, String selection, String[] selectionArgs) {
String modifiedSelection = selection;
switch (uriMatcher.match(uri)) {
case WIDGET_ID: {
modifiedSelection += " = " + uri.getLastPathSegment();
System.out.println(">>"+modifiedSelection);
}
}
int updateCount = 0;
updateCount = database.update(Schema.Table.TABLE_NAME,contentValues,modifiedSelection,null);
if (updateCount == 1) {
getContext().getContentResolver().notifyChange(uri,null);
}
return updateCount;
}
~SNIP~
~SNIP - skyfishjy
import android.content.Context;
import android.database.Cursor;
import android.database.DataSetObserver;
import android.support.v7.widget.RecyclerView;
/**
* Created by skyfishjy on 10/31/14.
*/
public abstract class CursorRecyclerViewAdapter<VH extends RecyclerView.ViewHolder> extends RecyclerView.Adapter<VH> {
private Context mContext;
private Cursor mCursor;
private boolean mDataValid;
private int mRowIdColumn;
private DataSetObserver mDataSetObserver;
public CursorRecyclerViewAdapter(Context context, Cursor cursor,boolean hasStableIds) {
mContext = context;
mCursor = cursor;
mDataValid = cursor != null;
mRowIdColumn = mDataValid ? mCursor.getColumnIndex("_id") : -1;
mDataSetObserver = new NotifyingDataSetObserver();
if (mCursor != null) {
mCursor.registerDataSetObserver(mDataSetObserver);
}
super.setHasStableIds(hasStableIds);
}
public Cursor getCursor() {
return mCursor;
}
@Override
public int getItemCount() {
if (mDataValid && mCursor != null) {
return mCursor.getCount();
}
return 0;
}
@Override
public long getItemId(int position) {
if (mDataValid && mCursor != null && mCursor.moveToPosition(position)) {
return mCursor.getLong(mRowIdColumn);
}
return 0;
}
@Override
public void setHasStableIds(boolean hasStableIds) {
super.setHasStableIds(true);
}
public abstract void onBindViewHolder(VH viewHolder, Cursor cursor);
@Override
public void onBindViewHolder(VH viewHolder, 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(viewHolder, mCursor);
}
/**
* Change the underlying cursor to a new cursor. If there is an existing cursor it will be
* closed.
*/
public void changeCursor(Cursor cursor) {
Cursor old = swapCursor(cursor);
if (old != null) {
old.close();
}
}
/**
* Swap in a new Cursor, returning the old Cursor. Unlike
* {@link #changeCursor(Cursor)}, the returned old Cursor is <em>not</em>
* closed.
*/
public Cursor swapCursor(Cursor newCursor) {
if (newCursor == mCursor) {
return null;
}
final Cursor oldCursor = mCursor;
if (oldCursor != null && mDataSetObserver != null) {
oldCursor.unregisterDataSetObserver(mDataSetObserver);
}
mCursor = newCursor;
if (mCursor != null) {
if (mDataSetObserver != null) {
mCursor.registerDataSetObserver(mDataSetObserver);
}
mRowIdColumn = newCursor.getColumnIndexOrThrow("_id");
mDataValid = true;
notifyDataSetChanged();
} else {
mRowIdColumn = -1;
mDataValid = false;
notifyDataSetChanged();
//There is no notifyDataSetInvalidated() method in RecyclerView.Adapter
}
return oldCursor;
}
public int getPositionForId(long id) {
mCursor.moveToFirst();
while (mCursor.moveToNext()) {
if (mCursor.getInt(0) == id) {
return mCursor.getInt(15);
}
}
return -1;
}
private class NotifyingDataSetObserver extends DataSetObserver {
@Override
public void onChanged() {
super.onChanged();
mDataValid = true;
notifyDataSetChanged();
}
@Override
public void onInvalidated() {
super.onInvalidated();
mDataValid = false;
notifyDataSetChanged();
//There is no notifyDataSetInvalidated() method in RecyclerView.Adapter
}
}
}
答案 0 :(得分:2)
我发现了问题,它没有在我的代码中列出 问题
@Override
public Cursor query(final Uri uri, final String[] projection,
final String selection, final String[] selectionArgs,
final String sortOrder) {
Log.d(TAG, "query()" + uri.toString());
String modifiedSelection = selection;
switch (uriMatcher.match(uri)) {
case WIDGET_ID: {
modifiedSelection += SchemaTable.ID
+ " = " + uri.getLastPathSegment();
break;
}
case WIDGETS: {
//return database.query(Schema.Table.TABLE_NAME, WidgetModel.getAllColumns(), selection, selectionArgs, null, null, sortOrder);
break;
}
default: {
//TODO log only when this is a debug build
throw new IllegalArgumentException("Unknown URI: " + uri);
}
}
return database.query(Schema.Table.TABLE_NAME,WidgetModel.getAllColumns(), modifiedSelection, selectionArgs, null, null, sortOrder);
}
这条线丢失了:
....setNotificationUri(getContext().getContentResolver(),uri);
然后使用以下代码替换return语句:
Cursor cursor = database.query(Schema.Table.TABLE_NAME, WidgetModel.getAllColumns(), modifiedSelection, selectionArgs, null, null, sortOrder);
cursor.setNotificationUri(getContext().getContentResolver(),uri);
return cursor;