Android CursorAdapter,ListView和后台线程

时间:2009-08-26 23:16:03

标签: java android

我一直致力于此应用程序的数据库具有多兆字节的数据进行筛选。许多活动只是ListViews,通过数据库中的各种级别的数据下行,直到我们到达“文档”,这只是从数据库中提取并在手机上显示的HTML。我遇到的问题是,其中一些活动需要能够通过捕获键击并使用“like%blah%”重新运行查询来搜索数据库。除非用户首次加载数据并且用户首次进入击键时,否则这种工作相当快。我正在使用ResourceCursorAdapter并且我在后台线程中生成光标,但是为了执行listAdapter.changeCursor(),我必须使用Handler将其发布到主UI线程。这个特殊的调用然后冻结UI线程足够长来调出可怕的ANR对话框。我很好奇如何将其完全卸载到后台线程,以便用户界面保持响应,并且我们没有弹出ANR对话框。

仅仅为了完全公开,我最初返回了一个自定义模型对象的ArrayList并使用了ArrayAdapter,但是(可以理解)客户指出这是一个糟糕的内存管理,我对性能反正不满意。我真的想避免一个解决方案,我正在生成大量的对象列表,然后做一个listAdapter.notifyDataSetChanged / Invalidated()

以下是相关代码:

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 个答案:

答案 0 :(得分:1)

我发现很难相信listAdapter.changeCursor()单独会花费足够的时间来引起ANR,假设您在后台线程中创建了Cursor。重绘少量列表行时,不应该做那么多工作。我会仔细检查你在Handler中做的工作是否有限。也许考虑使用AsyncTask,这样可以更容易地将后台工作(doInBackground())与on-UI线程后处理(onPostExecute())分开。

您可以尝试直接更换适配器,再次使用新适配器中包含的新setAdapter()再次调用Cursor

您可以查看AutoCompleteTextView如何处理此方案,因为它使用SpinnerAdapter进行动态过滤。也许它的一些技术可以适用于你的情况。

答案 1 :(得分:0)

刚刚在这里发布了一个答案:Android: Update Listview after Thread loads data from the net

  

简短:AsyncTask的onProgressUpdate方法可以触及视图:http://developer.android.com/reference/android/os/AsyncTask.html#onProgressUpdate(Progress...)