ListView.setListAdapter非常慢

时间:2011-08-21 21:02:48

标签: android performance listview

我有一个ListView,它可能包含由CursorAdapter生成的数千行。任何时候只能看到八行左右。我有报告称启动此视图可能需要几秒钟,并且可能导致ANR(强制关闭)。

我正在后台线程中进行数据库查询。我已经验证我的适配器中的newViewbindView仅针对可见行的数量进行调用。

显示列表后,实际上向上和向下滚动列表非常快。

延迟是在ListView.setListAdapter的调用中,它必须在UI线程上运行。为什么这似乎取决于结果集中的总行数,而不是实际显示的行数(小得多)?有什么方法可以优化它吗?

几年前就提出了这个问题in this thread。我希望能得到一些新的见解和更具体的解决方法。

更新

我尝试使用CommonsWare's EndlessAdapter来解决这个问题。我在我的数据库查询中使用LIMIT子句将初始查询限制为(比方说)20行,并且我增加此限制并在每次点击列表底部时重新提交查询。

(顺便说一句,我还没有找到一种方法将只是新的结果附加到现有的Cursor,所以我每次增加LIMIT值然后重新 - 在新的Cursor中获取整个批次的新限制。)

奇怪的是,这种解决方法似乎并没有改善执行初始setListAdapter调用所需的时间。当我在仅包含20行的数据集上运行它时,对setListAdapter的调用非常快。当我在包含数百行的数据集上运行它,但仅限于返回20时,则需要一秒钟。

更新2

通过强制查询在后台线程中使用简单的getCount()执行,如CommonsWare所建议的那样,我已经治愈了启动活动时UI线程的初始阻塞。但是,从子活动返回此活动时,UI仍会被阻止。默认情况下,ListActivity似乎想要在UI线程上重新运行查询。

我通过删除onStop()中的适配器并在onStart()中重新创建适配器来解决此问题。因此,无论我们在活动堆栈中移动的方向如何,查询总是在后台执行。

1 个答案:

答案 0 :(得分:4)

  

我正在后台线程中进行数据库查询

如果你在后台做的只是调用query()rawQuery(),则查询实际上并未执行。当您第一次尝试使用Cursor(例如getCount())时,它会被执行。因此,在后台执行查询的正确方法是rawQuery(),后跟后台线程中的getCount(),以确保查询真正执行。

  

当我在包含数百行的数据集上运行它,但仅限于返回20时,则需要一秒钟。

关闭袖带,这表明速度问题不是读取结果所需的时间,而是首先计算结果。