Android CursorAdapters, ListViews and Background Threads

This application I was working on has databases with several megabytes of data to sift through. Many of them are simply ListViews that descend through various levels of data in databases until we reach β€œdocuments” that are simply pulled from the database (DB) and displayed on the phone. The problem I'm running into is that some of these actions should be able to search through databases, capturing keystrokes and rerunning the query with "like% blah%" in it. This works reasonably fast, except when the user loads data first and when the user types a keystroke first. I am using ResourceCursorAdapter and I am generating cursor on background thread, but in order to do listAdapter.changeCursor (),I have to use a handler to send it to the main UI thread. This particular call then freezes the UI thread long enough to trigger the awful ANR dialog. I am curious how I can fully load this into a background thread to keep the UI responsive and we don't have ANR dialogs.

Just for full disclosure, I originally returned an ArrayList of custom model objects and used an ArrayAdapter, but (understandably) the client indicated it was poor memory management and I was still unhappy with the performance. I would really like to avoid a solution where I create huge lists of objects and then do listAdapter.notifyDataSetChanged / Invalidated ()

Here is the code in question:

private Runnable filterDrugListRunnable = new Runnable() {
    public void run() {
        if (filterLock.tryLock() == false) return;

        cur = ActivityUtils.getIndexItemCursor(DrugListActivity.this);

        if (cur == null || forceRefresh == true) {
            cur = docDb.getItemCursor(selectedIndex.getIndexId(), filter);
            ActivityUtils.setIndexItemCursor(DrugListActivity.this, cur);
            forceRefresh = false;
        }

        updateHandler.post(new Runnable() {
           public void run() {
               listAdapter.changeCursor(cur);
           }
        });

        filterLock.unlock();

        updateHandler.post(hideProgressRunnable);
        updateHandler.post(updateListRunnable);
    }
};

      

+2


source to share


2 answers


I find it hard to believe that it listAdapter.changeCursor()

would only take long enough to trigger the ANR if you created Cursor

on a background thread. There shouldn't be so much work that needs to happen to redraw multiple lines of the list. I would double check to see what kind of work you do in your Handler is limited as you think. Perhaps consider using AsyncTask, which will make it easier to separate background work ( doInBackground()

) from subsequent processing by UI thread ( onPostExecute()

).

You can try to simply replace the adapter directly by calling again setAdapter()

with a new Cursor

one wrapped in a new adapter.



You can see how AutoCompleteTextView

this script handles as it does filtering on the fly with SpinnerAdapter

. Perhaps some of his methods can be applied in your case.

+1


source


Just posted an answer here: Android: Refresh Listview after Thread downloads data from network



Short: AsyncTask's onProgressUpdate method can touch the view: http://developer.android.com/reference/android/os/AsyncTask.html#onProgressUpdate (Progress ...)

0


source







All Articles