Way to update UI after database change has occured
Asked Answered
P

2

7

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?

Physiological answered 5/12, 2014 at 8:49 Comment(4)
the item in the basket is combined with an insert operation in the database?Dato
Not quite sure what you mean but basically after the http request is completed I update corresponding row in the database table, which state should somehow be mirrored by the UI. My problem is that I can't seem to find a way to tell UI to update after DB data has been changed.Physiological
did you call notifyChange after you updated the row?Dato
is your sql query located in the adapter?or are you feeding only the arraylist to the adapter?Nafis
T
10

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.

Trochlear answered 5/12, 2014 at 9:14 Comment(0)
B
2

If you are using a list, you can fill adapter again and set it to your list. Or try to inform data set change.

Banjo answered 5/12, 2014 at 8:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.