问题
I have setup a fragment to pull data from a custom content provider using a CursorLoader.
The problem is that when i update a record in the SQLite table using the content resolver, the cursor does not refresh i.e. the getContext().getContentResolver().notifyChange(myUri, null)
has no effect. I have to exit the fragment and open it again to see the change.
I think the problem is that the URI i have used to update a row is not being observed by the loader :
- URI to create loader -
content://com.myapp.provider/MyTable/Set/22
- URI to update row -
content://com.myapp.provider/MyTable/167
167 identifies a unique row in the table. 22 identifies a set of rows in the table. Is there some way to tell the loader that the row 167 comes within the set 22, so it should reset the cursor?
Here is the code in case it brings more clarity :
Creating CursorLoader in Fragment :
@Override
public Loader<Cursor> onCreateLoader(int arg0, Bundle queryBundle) {
CursorLoader cursorLoader = new CursorLoader(getActivity(), Uri.parse("content://com.myapp.provider/MyTable/Set/22"), myProjection, null, null, null);
return cursorLoader;
}
on button click in fragment :
mContext.getContentResolver().update("content://com.myapp.provider/MyTable/167", values, null, null);
Content Provider class :
private static final String AUTHORITY = "com.myapp.provider";
private static final String TABLE_PATH = "MyTable";
public static final String CONTENT_URI_BASEPATH = "content://" + AUTHORITY + "/" + TABLE_PATH;
private static final int URITYPE_TABLE = 1;
private static final int URITYPE_SINGLE_SET = 2;
private static final int URITYPE_SINGLE_ROW = 3;
private static final UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
static{
sUriMatcher.addURI(AUTHORITY, TABLE_PATH,URITYPE_TABLE);
sUriMatcher.addURI(AUTHORITY, TABLE_PATH + "/Set/#", URITYPE_SINGLE_SET);
sUriMatcher.addURI(AUTHORITY, TABLE_PATH + "/#", URITYPE_SINGLE_ROW);
}
@Override
public int update(Uri myUri, ContentValues values, String selection, String[] selectionArgs){
int rowCount = 0;
String id;
SQLiteDatabase db = localDB.getWritableDatabase();
int uriType = sUriMatcher.match(myUri);
switch(uriType){
case URITYPE_SINGLE_ROW :
id = uri.getLastPathSegment();
//selection and selectionArgs are ignored since the URI itself identifies a unique row.
rowCount = db.update(MyTable.TABLE_NAME, values, MyTable.COLUMN_ID + " = ?", new String[] {id});
}
getContext().getContentResolver().notifyChange(myUri, null);
return rowCount;
}
回答1:
I has a similar issue and found the solution here.
In brief, it turned out I needed to call setNotificationUri(ContentResolver cr, Uri uri)
on the cursor returned by the query()
method of my content provider.
回答2:
The solution is to call notifyChange()
on the Uri that is being observed i.e. the set and not on the row.
To achieve this, we need to make some changes :
Include the set ID in the URI when calling the update :
mContext.getContentResolver().update("content://com.myapp.provider/MyTable/Set/22/167", values, null, null);
Change the URI pattern of a single row from "/#" to "/Set/#/#"
private static final UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH); static{ sUriMatcher.addURI(AUTHORITY, TABLE_PATH,URITYPE_TABLE); sUriMatcher.addURI(AUTHORITY, TABLE_PATH + "/Set/#", URITYPE_SINGLE_SET); sUriMatcher.addURI(AUTHORITY, TABLE_PATH + "/Set/#/#", URITYPE_SINGLE_ROW); }
Then in the update function, construct a new Uri that has to be notified :
List<String> pathSegments = uri.getPathSegments(); String mySetID = pathSegments.get(2); Uri mySetUri = Uri.parse("content://" + AUTHORITY + "/" + TABLE_PATH + "/Set/" + mySetID); getContext().getContentResolver().notifyChange(mySetUri, null);
来源:https://stackoverflow.com/questions/24465999/content-resolver-notifychange-not-working