android - CursorLoader & SQLite without Content Provider
The two implementations you mention in your post both offer all of the benefits of the CursorLoader
except the ability to receive notifications when the underlying content changes.
I've been looking into this a lot recently and I can confidently tell you that the Android API currently does not provide a means of doing this with only a raw SQLiteDatabase
(it only provides the ContentResolver#notifyChange()
and Cursor#setNotificationUri()
methods, which are used to notify all Cursor
s registered under a certain notification Uri
).
That said, your options right now are to:
Implement an observer yourself that is capable of receiving notifications from the
SQLiteDatabase
when the content changes, and is somehow able to relay these notifications to all existingLoader
s in your application. I wrote a pretty extensive blog post on how to implementLoader
s that might come in handy if you wish to take on this challenge. Or...Use Mark Murphy's
LoaderEx
library and only make database modifications using theAsyncTask
operations his library provides. Note that the reason why his tasks refresh theLoader
is because they callonContentChanged
on theLoader
immediately after the insertion/update/delete is performed, effectively telling theLoader
that the content has changed and that it should refresh its data.Just use a
ContentProvider
with aCursorLoader
and you can use theContentResolver#notifyChange()
method to notify theCursorLoader
that a content change has occurred.
I'm trying to figure out a better solution, and I'll report back in the future if I ever find/implement one, but for now these will have to do.
Here is my solution, in my onCreateLoader
{
Uri u = Uri.parse("content://what_string_you_want");
return new CursorLoader(this, yourURI, projection, null, null, null) {
private final ForceLoadContentObserver mObserver = new ForceLoadContentObserver();
@Override
public Cursor loadInBackground() {
Cursor c = YOUR_DATABASE.doYourQuery(...);
if (c != null) {
// Ensure the cursor window is filled
c.getCount();
c.registerContentObserver(mObserver);
}
c.setNotificationUri(getContext().getContentResolver(), getUri());
return c;
}
};
}
After the code that will change DB, add
getContentResolver().notifyChange(
Uri.parse("content://same_with_first_string"), null);