ListView.setListAdapter очень медленный - PullRequest
0 голосов
/ 22 августа 2011

У меня есть ListView, который потенциально содержит тысячи строк, сгенерированных CursorAdapter.Только восемь или около того строк видны одновременно.У меня были сообщения, что запуск этого представления может занять много секунд и может вызвать ANR (принудительное закрытие).

Я делаю запрос БД в фоновом потоке.Я убедился, что newView и bindView в моем адаптере вызываются только для количества видимых строк.

После отображения списка прокрутка вверх и вниз на самом деле происходит очень быстро.

Задержка в вызове ListView.setListAdapter, который должен выполняться в потоке пользовательского интерфейса.Почему это зависит от общего числа строк в наборе результатов, а не от (гораздо меньшего) количества строк, которые фактически отображаются?Можно ли как-нибудь оптимизировать его?

Этот вопрос был задан пару лет назад в этой теме .Я надеюсь получить некоторое свежее понимание и более конкретные примеры возможных обходных путей.

ОБНОВЛЕНИЕ

Я попытался обойти это, используя EndlessAdapter CommonsWare.Я ограничиваю исходный запрос, скажем, 20 строками, используя в своем запросе к БД выражение LIMIT, и я увеличиваю этот предел и повторяю запрос каждый раз, когда достигаю нижней части списка.

(КакКроме того, я не нашел способа добавления просто новых результатов к существующему Курсору, поэтому я увеличиваю значение LIMIT каждый раз, а затем заново извлекаю весь лот до новогоlimit в новом Cursor.)

Странно, но этот обходной путь, похоже, не уменьшает время, необходимое для выполнения начального вызова setListAdapter.Когда я запускаю его на наборе данных, содержащем только 20 строк, вызов setListAdapter действительно быстрый.Когда я запускаю его на наборе данных, содержащем сотни строк, но с ограничением возврата только 20, это занимает более секунды.

ОБНОВЛЕНИЕ 2

При форсировании запросачтобы выполнить в фоновом потоке с простым getCount(), как предложено CommonsWare, я вылечил первоначальную блокировку потока пользовательского интерфейса при запуске действия.Тем не менее, пользовательский интерфейс по-прежнему блокируется при возврате этого действия из дочернего действия.ListActivity по умолчанию, кажется, хочет повторно выполнить запрос в потоке пользовательского интерфейса.

Я обошел эту проблему, удалив адаптер в onStop() и воссоздав его в onStart().Таким образом, запрос всегда выполняется в фоновом режиме, независимо от того, в каком направлении мы движемся через стек действий.

1 Ответ

4 голосов
/ 22 августа 2011

Я делаю запрос БД в фоновом потоке

Если все, что вы делаете в фоновом режиме, это вызов query() или rawQuery(), запрос фактически не выполняется.Это будет выполняться с отложенным выполнением при первой попытке использования Cursor (например, getCount()).Итак, правильный рецепт для выполнения запроса в фоновом режиме - это rawQuery(), за которым следует что-то вроде getCount() в фоновом потоке, чтобы гарантировать, что запрос действительно выполняется.

Когда я его запускаюдля набора данных, содержащего сотни строк, но ограниченного возвращением только 20, это занимает более секунды.

С манжеты, это может указывать на то, что проблема скорости - это не время, необходимое для чтения врезультаты, а точнее в вычислении результатов в первую очередь.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...