Search code examples
androidandroid-sqliteandroid-contentproviderandroid-loader

Way to update UI after database change has occured


I'm developing an app based on Google IO presentation architecture using the first approach. Basically I have a Service, ContentProvider backed by SQLite DB and I also use Loaders.

I need a way to update UI when changes to my database occur. For instance a user might want to add an item into his basket. After I insert the item id into the basket table I want to update the UI. What approach should I use? I've seen very little information on ContentObserver so far. Is it the way to go?


Solution

  • In the query method of your ContentProvider attach a listener to the returned cursor:

     Cursor cursor = queryBuilder.query(dbConnection, projection, selection, selectionArgs, null, null, sortOrder);
     cursor.setNotificationUri(getContext().getContentResolver(), uri);
    

    Then in your insert/update/delete methods use code like this:

     final long objectId = dbConnection.insertOrThrow(ObjectTable.TABLE_NAME, null, values);
     final Uri newObjectUri = ContentUris.withAppendedId(OBJECT_CONTENT_URI, objectId );
     getContext().getContentResolver().notifyChange(newObjectUri , null);
    

    Your CursorLoader will be notified and the OnLoadFinished(Loader, Cursor) will be called again.

    If you're not using a Loader, the ContentObserver is the way to go, with a few lines of code you are notified on db changes (but you will need to requery manually).

      private ContentObserver objectObserver = new ContentObserver(new Handler()) {
        @Override
        public void onChange(boolean selfChange) {
            super.onChange(selfChange);
            restartObjectLoader();
        }
    };
    

    Remember to call in onResume():

     getContentResolver().registerContentObserver(ObjectProvider.OBJECT_CONTENT_URI, false, objectObserver);
    

    and in onPause():

     getContentResolver().unregisterContentObserver(objectObserver);
    

    Update: UI Changes This is a larger topic because it depends on the Adapter you use to fill the ListView or RecyclerView.

    CursorAdapter In onLoadFinished(Loader loader, Cursor data)

     mAdapter.swapCursor(data);
    

    ArrayAdapter In onLoadFinished(Loader loader, Cursor data)

     Object[] objects = transformCursorToArray(data); //you need to write this method
     mAdapter.setObjects(objects); //You need to wrie this method in your implementation on the adapter
     mAdapter.notifyDataSetChange();
    

    RecyclerView.Adapter In onLoadFinished(Loader loader, Cursor data)

     Object[] objects = transformCursorToArray(data); //you need to write this method
     //Here you have more mAdapter.notify....()
    

    Read from here for different way to notify the RecyclerView.Adapter.