How to implement ContentObserver in fragment using CursorAdapter and LoaderCallbacks?

I use CursorAdapter in ListFragment to load and display a list of comments.

 public class CommentsFragment extends ListFragment implements LoaderCallbacks<Cursor> { protected Activity mActivity; protected CursorAdapter mAdapter; @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); mActivity = getActivity(); mAdapter = new CommentsCursorAdapter(mActivity, null, 0); setListAdapter(mAdapter); mActivity.getContentResolver().registerContentObserver(CustomContract.Comments.CONTENT_URI, false, new CommentsObserver()); getLoaderManager().initLoader(0, null, this); } @Override public Loader<Cursor> onCreateLoader(int id, Bundle extras) { Uri uri = CustomContract.Comments.CONTENT_URI; return new CursorLoader(mActivity, uri, null, null, null, null); } @Override public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) { mAdapter.swapCursor(cursor); } @Override public void onLoaderReset(Loader<Cursor> loader) { mAdapter.swapCursor(null); } protected class CommentsObserver extends ContentObserver { public CommentsObserver() { super(new Handler()); } @Override public void onChange(boolean selfChange) { super.onChange(selfChange); // TODO Trigger a reload. } } } 

In the related ContentProvider, I added notifyChange() for the insert action.

 @Override public Uri insert(Uri uri, ContentValues values) { final SQLiteDatabase db = mOpenHelper.getWritableDatabase(); int match = sUriMatcher.match(uri); switch (match) { case COMMENTS: { long id = db.insert(DatabaseProperties.TABLE_NAME_COMMENTS, null, values); Uri itemUri = ContentUris.withAppendedId(uri, id); // FIXME Which one is right? getContext().getContentResolver().notifyChange(itemUri, null); getContext().getContentResolver().notifyChange(uri, null); return itemUri; } default: { throw new UnsupportedOperationException("Unknown URI: " + uri); } } } 

Questions:

  • Is it possible to pass null to notifyChange() as an observer parameter? If not, what object should I go through here?
  • Should I pass uri or itemUri to notifyChange() ? Why?
  • Which method should I call in CommentsObserver#onChange() to update the list of comments?
  • Is there an interface that I could implement using ListFragment instead of an internal instance of the ContentObserver class?
  • I just create an instance of new Handler() in the CommentsObserver constructor. It seems to me wrong - please explain.
+4
source share
1 answer

SqlCursor already has an internal ContentObserver , and since you are using this implementation of Cursor , there is no need for a custom implementation of ContentObserver .

For ease of use, you can add:

 class MyContentProvider extends ContentProvider{ //rest implementation goes here @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { Cursor cursor = null; //check uri, select table name based on uri, etc ... cursor = db.query(/*.....*/); //add this line: cursor.setNotificationUri(getContext().getContentResolver(), uri); //before you return cursor return cursor; } @Override public Uri insert(Uri uri, ContentValues values) { /* ... */ //you can notify only "dir" uri and is should be enough getContext().getContentResolver().notifyChange(uri, null); return itemUri; /* ... */ } //rest of implementation goes here } 

after that, the internal implementation of CursorLoader will take care of reloading / updating data ...

+12
source

All Articles