Решение: getView в ListView вызывается многократно в Android

Пройдите тест, узнайте какой профессии подходите и получите бесплатную карьерную консультацию
В конце подарим скидку до 55% на обучение
Я предпочитаю
0%
Работать самостоятельно и не зависеть от других
Работать в команде и рассчитывать на помощь коллег
Организовывать и контролировать процесс работы

Быстрый ответ

Чтобы повысить производительность ListView, настоятельно рекомендуется применять паттерн ViewHolder. Это позволяет избежать ненужных операций "inflate" и поиска вью. Приведём пример реализации метода getView():

Java
Скопировать код
public View getView(int position, View convertView, ViewGroup parent) {
    ViewHolder holder;
    if (convertView == null) {
        convertView = LayoutInflater.from(context).inflate(R.layout.item_layout, parent, false);
        holder = new ViewHolder(convertView);
        convertView.setTag(holder); // Связываем объект ViewHolder с вью.
    } else {
        holder = (ViewHolder) convertView.getTag(); // Извлекаем объект ViewHolder из вью.
    }

    // Устанавливаем данные.
    holder.itemTitle.setText(getItem(position).getTitle());

    return convertView;
}

// Внутренний класс ViewHolder, содержащий ссылки на компоненты вью.
static class ViewHolder {
    final TextView itemTitle;

    ViewHolder(View view) {
        itemTitle = (TextView) view.findViewById(R.id.itemTitle);
    }
}

Переиспользуйте вью и старайтесь как можно меньше использовать метод findViewById(). Это обеспечивает плавную прокрутку и улучшает пользовательский опыт.

Корректное определение размера ListView

Специфика метода getView() заключается в его неочевидном поведении, что влияет на производительность ListView. Рекомендуется избегать применения wrap_content при определении размеров списков во избежание лишнего пересчёта макета.

Фиксация высоты ListView

Применение wrap_content в атрибуте layout_height приводит к многократному вычислению размеров элементов, что негативно влияет на производительность. Для достижения наилучшего результата используйте фиксированную высоту или рассмотрите возможность использования RecyclerView.

Оптимизация элементов списков

Установка layout_width и layout_height элементов списка как match_parent способствует ускорению их отрисовки за счёт единичного измерения.

Переиспользование вью: причины и способы

ListView, переиспользуя вью, ведёт себя как энергичный диджей в процессе прокрутки, экономя память и вычислительные ресурсы.

Эффективный ListView с использованием ViewHolder

Важнейшим правилом работы с ListView является применение статического ViewHolder. Эта техника регулирует вызовы getView() и предотвращает ошибки отображения, связанные с повторным использованием элементов. ViewHolder сохраняет статичные элементы интерфейса, что позволяет списку быстрее обновляться при изменении данных.

Количество вызовов getView() зависит от размера ListView

Оптимальное определение размеров ListView позволяет уменьшить количество вызовов метода getView(). Правильно выбранные атрибуты макета для ListView и его элементов обеспечивают эффективную работу компонента.

Паттерн ViewHolder: упрощение раздувания

Раздувание вью — это процесс, требующий значительных ресурсов. Использование ViewHolder упрощает эту процедуру, позволяя повторное использование вью и сокращая количество вызовов getView().

Визуализация

Метод getView() можно сравнить с фокусником, перетасовывающим колоду карт:

Колода (🎴): [Карта 1, Карта 2, Карта 3, ..., Карта n] Перетасовка (🔄): getView() может выбрать любую карту в любой момент.

Обратите внимание: благодаря механизму переиспользования ListView может вызывать getView() многократно и в произвольном порядке для экономии памяти.

Приведение в порядок вызовов getView()

ListView может вызвать getView() для конкретной позиции несколько раз в процессе расчета размеров. Как разработчики, мы должны понимать, что ListView подготавливает вью к разнообразным взаимодействиям со стороны пользователя, например, к скроллингу или свайпу.

Управление изменениями данных

При изменении данных ListView обновляет представление, вызывая getView() в случайном порядке. Важно правильно обновлять набор данных адаптера для корректного отображения изменений в ListView.

Предзагрузка и переходы

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

Полезные материалы

  1. Использование ArrayAdapter с ListView | Шпаргалка Android CodePath — подробное изложение применения ArrayAdapter в Android.
  2. Оптимизация списка в Android с помощью ListView – Учебник от Vogella — как оптимизировать ListView используя паттерн ViewHolder.
  3. Блог разработчиков Android: Многопоточность для повышения производительности — усовершенствование ваших навыков работы с ListView и многопоточности для повышения производительности Android.
  4. Макеты в Android | Разработчики Android — о формировании макетов с AdapterView на официальном сайте Android.
  5. Как осуществить "ленивую" загрузку изображений в ListView на Android – Stack Overflow — советы по повышению производительности и подходы к оптимизации загрузки изображений.
  6. Руководство по работе с ListView на Android – Techotopia — анализ типичных проблем и рекомендации по предотвращению повторения элементов в ListView.