1

I've implemented my custom ContentProvider and it has several URIs:

The main one:

//Return all items, uriType = ALLITEMS
String BASEURI = "content://authority/items"

and

//Return all items in category #, uriType = ITEMS
"content://authority/items/cat/#" 
//Return all items in category # starting with *, uriType = ITEMS_INITIAL
"content://authority/items/cat/#/*"

My Activity implements these Loader callbacks:

@Override
public Loader<Cursor> onCreateLoader(int id, Bundle arg1) {
    CursorLoader mCursorLoader = null;
    switch (id) {
    case 0:
        mCursorLoader = new CursorLoader(
                mActivity,
                Uri.parse("content://authority/items/cat/"
                        +mCurrentID), mColumns, null, null, null);
        break;
    }
    return mCursorLoader;
}

@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
    switch (loader.getId()) {
    case 0:
        cursor.setNotificationUri(getContentResolver(),MyContentProvider.BASEURI);
        if (null == mAdapter)
            mAdapter = new GridViewCursorAdapter(this, cursor,0);
        //gv is a GridView
        if (gv.getAdapter() != mAdapter)
            gv.setAdapter(mAdapter);
        if (mAdapter.getCursor() != cursor)
            mAdapter.swapCursor(cursor);
        break;
    }
}

@Override
public void onLoaderReset(Loader<Cursor> arg0) {
    mAdapter.swapCursor(null);
}

When I want to insert data I use:

for (ItemClass item : itemsToInsert) {
    getContentResolver().insert(MyContentProvider.BASEURI, itemToContentValues(item));
}

And finally insert method in MyContentProvider is so defined:

@Override
public Uri insert(Uri uri, ContentValues values) {
    SQLiteDatabase database = db.getWritableDatabase();
    int turiType = sURIMatcher.match(uri);
    long id = 0;
    switch (uriType) {
    case ALLITEMS:
        id = database.insert(MySQLiteHelper.TABLE_ITEMS, null, values);
        break;
    default:
        throw new IllegalArgumentException("Unknown URI (" + uri + ")");
    }
    getContext().getContentResolver().notifyChange(uri, null);
    return null;//I will implement uri path to single item later
}

As you can see, the default URI used to initialize the Loader is the filter by category id and not the BASEURI one, but I used Cursor.setNotificationUri to set the notification URI to BASEURI, but the content of my GridView isn't updated.

If I restart the Activity I can see the inserted data, so it's just the notification that doesn't work. What should I change to get the loader notified properly?

Vektor88
  • 4,841
  • 11
  • 59
  • 111
  • Do you get updates if you remove the `setNotificationUri()` line entirely? – ianhanniballake Oct 16 '14 at 12:48
  • Also, is there a particular reason you chose to do filtering with a different URI vs using a where statement? – ianhanniballake Oct 16 '14 at 12:56
  • @ianhanniballake 1- If I remove the `setNotificationUri` entirely I see no changes. I only see the preexisting data. 2- I used two different URIs because I'm still learning, just now I realized that cursorloader constructor has selection and selectionArgs parameters. I'll try to simplify the code – Vektor88 Oct 16 '14 at 13:03
  • could you test one thing: try to remove last slash in BASEURI – Selvin Oct 16 '14 at 13:27
  • @Selvin sorry, when editing the code to make it more "generic" i added an extra slash, it's not present in my original code. I've edited the question too. – Vektor88 Oct 16 '14 at 13:55

1 Answers1

2

The best way to do filtering in a ContentProvider (and any database), is by using a where statement. In this case, that would mean your CursorLoader would look something like:

mCursorLoader = new CursorLoader(
  mActivity,
  MyContentProvider.BASEURI,
  mColumns, 
  MyContentProviderColumns.CATEGORY + "=?", // category = ?
  new String[] { Integer.toString(mCurrentID) }, // pass in your category
  null);

Passing in the selection, filtering on whatever your category column is called, and the selection args being the category value itself. In this case, you only have one URI, so notifications of changes are much easier to manage.

If you really, really need separate URIs, the other option is to do multiple notify calls in your insert statement:

getContext().getContentResolver().notifyChange(uri, null);

int category = extractCategoryFromContentValues(values);
getContext().getContentResolver().notifyChange("content://authority/items/cat/"
                    + category, null);
ianhanniballake
  • 191,609
  • 30
  • 470
  • 443