问题
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 mCustomCursorAdapter.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?
回答1:
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.
回答2:
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
来源:https://stackoverflow.com/questions/3544913/android-how-to-use-cursoradapter