I have a ListView populated via a CursorAdapter. I give my user the ability to alter the data in the list. For example, the user can mark a row as being unread (the data are messages).
Suppose my user marked a row unread. Would a proper implementation mark the row in the database as read and then requery the Cursor?
Would a proper implementation mark the row in the database as read and then requery the Cursor?
Yes, that's the right answer. The requery() will trigger an automatic update of your CursorAdapter, which will trigger an automatic update of the ListView, which will trigger an automatic smile from the user. :-)
UPDATE
The requery() method is deprecated. A better approach nowadays is to run a query to get a fresh Cursor, then use changeCursor() or swapCursor() on your CursorAdapter.
If the cursor is back by a ContentProvider and the ContentProvider issues correct notifications, the CursorAdapter will automatically refresh itself i.e. without the need to issue an explicit requery().
Related
In the delete method of my ContentProvider, I have this notification instruction:
getContext().getContentResolver().notifyChange(url, null);
CursorAdapters does not refresh the view when the user deletes something.
What's wrong?
It works for insert and update operations.
Maybe a bit late but for anyone else, you should call
cursor.setNotificationUri()
in the query() method of your content provider before returning the cursor to the caller.
For example in the android contacts content provider:
ContactsProvider2.java
This is because the CursorAdapter.java class registers a content observer on the cursor to requery on change.
Edit: reading your question again, that may not have been the problem.
I have some trouble when using CursorLoader... I want to download data from inet API page by page, however;
I also want to make pagination of the listview. It means that data should be downloaded page by page when the end of listview is reached.
I also want to filter my listview inputing constraint-text in AutocompleteTextView.
Each of these features works properly when I use them separately, but when I want use them together it works not pretty well. I want to implement such a scenario: if I entered filter-text in AutocompleteTextView my listview was invalidated (that works fine) and downloading process would start until listview size reach the end of screen.
The problem is I don't know how to organize the cursor update through CursorLoader, when I should restart loader and when should't I? Should I restart loader only when I set filter (setFilterQueryProvider, method runQuery(CharSequence constraint)) or should I do it when give new portion of data from inet?
Now when process was started I found out that callback onLoadFinished wasn't called and listview wasn't updated...
Maybe anybody give me some working example...
You could change your CursorLoader for an AsyncTaskLoader to fetch new information when no records found according to the filter criteria. With the AsyncTaskLoader you could handle DB and UI operations to manage the Activity's state when it is downloading data or querying it locally.
Hope it helps.
I use standard android ContentProvider and CursorLoader from support library.
I am looking for best approach for obtain information about what has changed in database.
I know that I can read and compare cursor in function:
#Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
}
but reading all records is probably not good solution.
Do you know good solution for this problem?
If you use a content provider, you abstract away all the changes made to the underlying database by implementing CRUD methods to insert, update, delete or retrieve an item in the database.
Sending a broadcast from the methods which you are interested would be an option to get notified of the changes being made to the database.
I recall that I had used this method to count the number of items added to the database during a refresh cycle.
Optionally you can send the Uri of the changed item as an intent extra to get a reference to the row in the database that has been changed.
Additionally you can declare a global variable to enable or disable these broadcasts to fire only during situations of interest to us.
while reading the documentation on Cursor here I read that cursor provides read/write access. I had gone through the API methods of Cursor but there is no setter method available to write into the Cursor. It would be of great help if you could provide me with code snippet. Thanks in advance
I think that's a bug in the documentation. You are quite right that there are no Cursor methods to modify the underlying data.
If you do try to modify the underlying data (by executing SQL statements, for example) while iterating over the data using a Cursor, bad things happen. If you need to make changes, you should keep a separate record of what you need to change whilst iterating with the Cursor, and then apply those changes separately once the Cursor is safely closed.
I have a following situation in my android app.
I have an app that fetches messages from inbox, sent items and drafts based on search keywords. I use to accomplish this by fetching cursors for each manually based on selection by user and then populating them in a custom data holder object. Filter those results based on given keywords and then manually render view with respective data.
Someone suggested that I should use a custom Cursor adapter to bind view and my cursor data. So I tried doing that. Now what I am doing is this:
Fetch individual cursors for inbox, sent items and drafts. Merge them into one using Merge cursor and then pass that back to my CursorAdapter implmentation.
Now where or how do I filter my cursor data based on keywords; because now binding will ensure that they are directly rendered to view on list. Also, some post fetching operation like fetching sender's contact pic and all will be something that I do not want to move to adapter. If I do all this processing in adapter; it'll be heavy and ugly.
How could I have designed it better such that it performs and the responsibilities are shared and distributed.
Any ideas will be helpful.
Using cursors and adapters does not work out well for the most part. Our experience as led down a different technique.
Your best bet is to "pump" the cursors in an AsyncTask into an ArrayList<data-holding object>, then you can do processing and then sort that list as necessary with Collections.sort() and the Comparator of your own construction, and then use ArrayAdapter to present the resulting list. This releases cursors ASAP and stays off the UI thread while doing it and you can sort however you feel like.
Remember always process in the background and avoid ANR!
We use this in all of our apps (14 on The Market) and it works like Butter.