I have a content provider, a content recognizer, and a cursor downloader. The loader is used to indirectly populate the list (i.e., not a simple cursor adapter, but an array adapter, since I need to use the cursor results to collect other data).
When I change the underlying data, the list view is not populated again, since the onLoadFinished(Loader<Cursor>, Cursor) not called.
As expected, while I am writing this, there are many questions on this subject. e.g. CursorLoader does not update after data change
And all the questions point to two things:
- In the query () method of your content provider, you must inform the cursor about a'la notifications
c.setNotificationUri(getContext().getContentResolver(), uri);
- In the insert / update / delete method of your content provider, you must notify the URI of this:
getContext().getContentResolver().notifyChange(uri, null);
I do these things.
I also DO NOT close the cursors that return to me.
Please note that my content provider lives in a separate application (think of it as a content provider application - without the main launch activity). The APK file is com.example.provider, and com.example.app calls (in the content resolver) through the content URI: //com.example.provider/table, etc. The content resolver (dbhelper) is located in the library project. (com.example.appdb) that the action refers to. (Thus, several projects can use dbhelper via links, and all content providers are installed through one APK)
I turned on debugging in the bootloader manager and see where I force the data to be updated after changing the data (i.e. restarting the bootloader and marking the previous one as inactive), but nothing that says that something happens automatically is more likely in response on my strength to freshen up.
Any ideas why my bootloader is not updating?
- UPDATE -
The loader creates:
Log.d(TAG, "onCreateLoader ID: " + loaderID); // typically a switch on the loader ID, and then return dbHelper.getfoo()
Where getfoo () returns the cursor loader via:
return new CursorLoader(context, FOO_URI, foo_Fields, foo_query, foo_argArray, foo_sort );
Loader Finish takes the cursor and fills the table (and does some processing) - thereβs nothing complicated.
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) { Log.d(TAG, "onLoadFinished id: " + loader.getId());
Loader Reset clears the table.
public void onLoaderReset(Loader<Cursor> loader) { Log.d(TAG, "onLoaderReset id: " + loader.getId());
The content provider does:
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { Cursor cursor; SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); SQLiteDatabase db = dbHelper.getReadableDatabase(); switch (sUriMatcher.match(uri)) { case FOO: qb.setTables(FOO); qb.setProjectionMap(FooProjectionMap); break; default: throw new IllegalArgumentException("Unknown URI " + uri); } Cursor c = qb.query(db, projection, selection, selectionArgs, null, null, sortOrder); c.setNotificationUri(getContext().getContentResolver(), uri); return c; }
Then insert / update similarly:
public Uri insert(Uri uri, ContentValues initialValues) { ContentValues values; if (initialValues != null) { values = new ContentValues(initialValues); } else { values = new ContentValues(); } String tableName; Uri contentUri; switch (sUriMatcher.match(uri)) { case FOO: tableName = FOOTABLE; contentUri = FOO_URI; break; default: throw new IllegalArgumentException("Unknown URI " + uri); } SQLiteDatabase db = dbHelper.getWritableDatabase(); long rowId = db.insert(tableName, null, values); if (rowId > 0) { Uri objUri = ContentUris.withAppendedId(contentUri, rowId); getContext().getContentResolver().notifyChange(objUri, null); return objUri; } throw new SQLException("Failed to insert row into " + uri); }