I have a database, a ListView
, and a CustomCursorAdapter
that extends CursorAdapter
. A menu button adds an item to the database. I want the ListView
to update and show this change. Normally it doesn't show this new item until i go to the homescreen and reopen the application.
I did eventually get it to work by calling cursor.requery()
or mCusto开发者_如何转开发mCursorAdapter.changeCursor(newCursor)
whenever I added a new item, but when I set autoRequery to false in the CursorAdapter
constructor, it worked just the same. Why does it update correctly when autoRequery is set to false?
Am I using CursorAdapter
correctly? What is the standard way of keeping the list updated with the database? And what does autoRequery do?
The idiomatic and imho correct way to automatically update Cursor
s is to call Cursor#setNotificationUri
when they are created and before they are handed off to whatever requested them. Then call ContentResolver#notifyChange
when anything in that Cursor
's Uri's namespace changes.
For example, suppose you were creating a simple mail application and you wanted to update when new mail arrived but also provide various views on the mail. I'd have some basic Uri's defined.
content://org.example/all_mail
content://org.example/labels
content://org.example/messages
Now, say I wanted to get a cursor that gave me all mail and be updated when new mail arrives:
Cursor c;
//code to get data
c.setNotificationUri(getContentResolver(), Uri.parse("content://org.example/all_mail");
Now new mail arrives so I notify:
//Do stuff to store in database
getContentResolver().notifyChange(Uri.parse("content://org.example/all_mail", null);
I should also notify all the Cursor
s that selected for labels this new message met
for(String label : message.getLabels() {
getContentResolver().notifyChange(Uri.parse("content://org.example/lables/" + label, null);
}
And also, maybe a cursor is viewing that one specific message so notify them as well:
getContentResolver().notifyChange(Uri.parse("content://org.example/messages/" + message.getMessageId(), null);
The getContentResolver()
calls happen where the data is accessed. So if it's in a Service
or ContentProvider
that is where you setNotificationUri
and notifyChange
. You should not be doing that from where the data is accessed, e.g., an Activity
.
AlarmProvider
is a simple ContentProvider
that uses this method to update Cursor
s.
I created next method for ListView updating:
/**
* Method of refreshing Cursor, Adapter and ListView after database
* changing
*/
public void refreshListView() {
databaseCursor = db.getReadableDatabase().query(
CurrentTableName,
null,
null,
null,
null,
null,
"title"+SortingOrder);
databaseListAdapter = new DomainAdapter(this,
android.R.layout.simple_list_item_2,
databaseCursor,
new String[] {"title", "description"},
new int[] { android.R.id.text1, android.R.id.text2 });
databaseListAdapter.notifyDataSetChanged();
DomainView.setAdapter(databaseListAdapter);
}
end calls it each time after some changing in database
精彩评论