ContentObserver for SQLite?
Asked Answered
M

1

2

I've been looking into ways to show data from my DB in a ListView while keeping track of changes in the database.

Let's say I have a chat app that shows a ListView of all the chatrooms I am a member of.

the query for the adapter is SELECT * FROM CHAT_ROOM ORDER BY UPTDATE_TIME, meaning I want the chatrooms with recent activity to be shown first. as I am in the ChatroomListActivity a message is received for chatroom number 3, this means it needs to become now chatroom number one and rearrange the cell accordingly.

I know that Loaders are capable of re-querying in the background but as commonsware answered in my previous question here, it seems like Loaders are not good enough for this.

is there a different mechanism for observing database changes in realtime?

Martineau answered 21/11, 2012 at 7:12 Comment(5)
thats why i love ContentProvider ... you can easily insert/update/delete even from other app(if you allow this) and still get informed about changes in other...Ionogen
in this case, I have to use a Database and not content provider.Martineau
why? you can wrap Database in ContentProvider then in update/inser/delete you just have to add getContext().getContentResolver().notifyChange(uri) and if you use similar uri in query that query/Cursor will be informed about changes ... this is supported in ListView so you dot need to write code for refreshing itIonogen
check this project ... its my helper library(with sample) which autogenerate content provider at runtime from anotationsIonogen
I am just curious, but did my answer help in any way ? and did you found a solution to your question ?Telegraph
T
4

The way I did it

  • Class GroupChatActivity
  • Class MessageDataSource
  • Class HandleNewMessage

The GroupChat Activity is kinda obvious. MessageDataSource the class that inserts and returns objects from the DB. HandleNewMessage, dont think I need to explain this one.

  • GroupChat -> MessageDataSource -> getMessages()
  • HandleNewMessage -> MessageDataSource -> insertNewMessage();

wat you now want is that the GroupChat & HandleNewMessage talk with the same instance of MessageDataSource. So you what you want to do is make a static reference to MessageDataSource with in the MessageDataSource Example:

 public class MessageDataSource {

    private static MessageDataSource mInstance;

    public static MessageDataSource getInstance(Context context) {
        if(mInstance == null){
            mInstance = new MessageDataSource(context);
        }
        return mInstance;
    }

    private MessageDataSource(Context context) {
        // NOTE: private constructor
    }
}

Because you make your constructor private you can't do

MessageDataSource data = new MessageDataSource(context);

Because the constructor is private you must do

MessageDataSource data = MessageDataSource.getInstance(context);

now your classes GroupActivity and HandleNewMessage can talk to the same instance of your MessageDataSource you can make an custom Interface that notifies any observing listener.

Example:

    public class MessageDataSource {

    private static MessageDataSource mInstance;

    private SQLiteDatabase mDataBase;
    private SQLiteHelper DBHelper;
    private OnInsert mOnInsert;

    public static MessageDataSource getInstance(Context context) {
        if(mInstance == null){
            mInstance = new MessageDataSource(context);
        }
        return mInstance;
    }

    private MessageDataSource(Context context) {
        DBHelper = SQLiteHelper.getInstance(context);
    }

    public void createMessage(String JID, String message, String sender) {
        // Do DB Stuff here
        if(mOnInsert != null) {
            mOnInsert.onInsert(message);
        }
    }


    public void setOnInsertListener(final OnInsert onInsert) {
        mOnInsert = onInsert;
    }

    public static interface OnInsert {
        // Notify the observer that an insert has bin made
        public String onInsert(String message);
    }
}

You can send as many Objects through a interface you think you require. Now in your GroupChatActivity you can set (in my case) a OnInserListener the normal way you would set an OnClickListener. Or you can let you Activity Implement the Interface.

This example does maby not qualify for you exact needs, but to observe when something new is inserted into you DB and you need to update your listView, this is in my opinion the way to go, but if someone finds a better way please comment. :D

I hope this can get you in the right direction.

Kind regards.

Telegraph answered 21/11, 2012 at 7:58 Comment(2)
What bothers me is that the context you are using to initialize the MessageDataSource could become invalid (e.g. activity restarts). Because of this, I'd create my instance of MessageDataSource in my Application class.Millen
This is definitely another fast way of doing it that might actually fit my needs. I have a foreground service (push notification) that manipulates my database and I use priority broadcasts and LocalBroadcastManager for dispatching events to activities. I will have to refactor my code to this model. Thanks.Readable

© 2022 - 2024 — McMap. All rights reserved.