У меня есть ListView, который потенциально содержит тысячи строк, сгенерированных CursorAdapter.Только восемь или около того строк видны одновременно.У меня были сообщения, что запуск этого представления может занять много секунд и может вызвать ANR (принудительное закрытие).
Я делаю запрос БД в фоновом потоке.Я убедился, что newView
и bindView
в моем адаптере вызываются только для количества видимых строк.
После отображения списка прокрутка вверх и вниз на самом деле происходит очень быстро.
Задержка в вызове ListView.setListAdapter
, который должен выполняться в потоке пользовательского интерфейса.Почему это зависит от общего числа строк в наборе результатов, а не от (гораздо меньшего) количества строк, которые фактически отображаются?Можно ли как-нибудь оптимизировать его?
Этот вопрос был задан пару лет назад в этой теме .Я надеюсь получить некоторое свежее понимание и более конкретные примеры возможных обходных путей.
ОБНОВЛЕНИЕ
Я попытался обойти это, используя EndlessAdapter CommonsWare.Я ограничиваю исходный запрос, скажем, 20 строками, используя в своем запросе к БД выражение LIMIT
, и я увеличиваю этот предел и повторяю запрос каждый раз, когда достигаю нижней части списка.
(КакКроме того, я не нашел способа добавления просто новых результатов к существующему Курсору, поэтому я увеличиваю значение LIMIT
каждый раз, а затем заново извлекаю весь лот до новогоlimit в новом Cursor.)
Странно, но этот обходной путь, похоже, не уменьшает время, необходимое для выполнения начального вызова setListAdapter
.Когда я запускаю его на наборе данных, содержащем только 20 строк, вызов setListAdapter
действительно быстрый.Когда я запускаю его на наборе данных, содержащем сотни строк, но с ограничением возврата только 20, это занимает более секунды.
ОБНОВЛЕНИЕ 2
При форсировании запросачтобы выполнить в фоновом потоке с простым getCount()
, как предложено CommonsWare, я вылечил первоначальную блокировку потока пользовательского интерфейса при запуске действия.Тем не менее, пользовательский интерфейс по-прежнему блокируется при возврате этого действия из дочернего действия.ListActivity
по умолчанию, кажется, хочет повторно выполнить запрос в потоке пользовательского интерфейса.
Я обошел эту проблему, удалив адаптер в onStop()
и воссоздав его в onStart()
.Таким образом, запрос всегда выполняется в фоновом режиме, независимо от того, в каком направлении мы движемся через стек действий.