我有一个ListView,它可能包含由CursorAdapter生成的数千行。任何时候只能看到八行左右。我有报告称启动此视图可能需要几秒钟,并且可能导致ANR(强制关闭)。
我正在后台线程中进行数据库查询。我已经验证我的适配器中的newView
和bindView
仅针对可见行的数量进行调用。
显示列表后,实际上向上和向下滚动列表非常快。
延迟是在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()
中重新创建适配器来解决此问题。因此,无论我们在活动堆栈中移动的方向如何,查询总是在后台执行。
答案 0 :(得分:4)
我正在后台线程中进行数据库查询
如果你在后台做的只是调用query()
或rawQuery()
,则查询实际上并未执行。当您第一次尝试使用Cursor
(例如getCount()
)时,它会被执行。因此,在后台执行查询的正确方法是rawQuery()
,后跟后台线程中的getCount()
,以确保查询真正执行。
当我在包含数百行的数据集上运行它,但仅限于返回20时,则需要一秒钟。
关闭袖带,这表明速度问题不是读取结果所需的时间,而是首先计算结果。