问题
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?
回答1:
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.
来源:https://stackoverflow.com/questions/13488090/contentobserver-for-sqlite