Методы getViewTypeCount и getItemViewType объекта ArrayAdapter

159

Может кто-нибудь в простых словах объяснить мне использование getViewTypeCount()и getItemViewType()методы ArrayAdapter?

Евгений
источник

Ответы:

308

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

@Override
public int getViewTypeCount() {
    return 2;
}

@Override
public int getItemViewType(int position) {
    return position % 2;
}

Фреймворк использует ваш тип представления, чтобы решить, через какие представления передать вам convertViewваш getViewметод . Другими словами, в приведенном выше примере ваши четные строки получат только переработанные виды с изображениями на левой стороне для повторного использования, а нечетные строки получат только те, на которых есть изображения справа.

Если каждая строка в вашем списке имеет одинаковое расположение, вам не нужно беспокоиться о типах представлений. На самом деле BaseAdapter.java обеспечивает поведение по умолчанию для всех адаптеров:

public int getItemViewType(int position) {
    return 0;
}

public int getViewTypeCount() {
    return 1;
}

Это действительно дает вам один и тот же тип представления для каждой строки.

Изменить - обрисовать общий ход:

  1. Вы связываете данные с AdapterViewиспользованием адаптера.
  2. В AdapterViewпытается отобразить элементы, которые видны пользователю.
  3. Фреймворк требует getItemViewTypeстроки n, строки, которую он собирается отобразить.
  4. Инфраструктура проверяет свой переработанный пул представлений на предмет просмотра типа строки n. Это не находит, потому что никакие представления еще не были переработаны.
  5. getViewназывается для ряда n.
  6. Вы вызываете getItemViewTypeстроку, nчтобы определить, какой тип представления следует использовать.
  7. Вы используете оператор if / switch для раздувания другого xml-файла в зависимости от того, какой тип представления требуется.
  8. Вы заполняете представление информацией.
  9. Вы возвращаете представление, выходя getView, и представление вашей строки отображается пользователю.

Теперь, когда представление перерабатывается путем прокрутки экрана, оно переходит в пул переработанных представлений, который управляется платформой. По сути, они организованы по типу представления, поэтому представление правильного типа дается вам в convertViewпараметре вашего getViewметода:

  1. Каркас снова вызывает getItemViewTypeстроку, которую хочет отобразить.
  2. На этот раз есть вид на переработанный пул соответствующего типа.
  3. Восстановленное представление передается вам в качестве convertViewпараметра вашего getViewметода.
  4. Вы заполняете переработанное представление новой информацией и возвращаете ее.
Мэтью Уиллис
источник
1
@ Мэтью, спасибо за ответ. Можете ли вы описать поток, как эти методы вызываются. Также я не понимаю, как это на самом деле связано с моими данными в res / layout.
Евгений
Нет явного контракта, когда эти методы вызываются. res / layout это место для просмотра объектов. Это адаптер . Вы должны проверить тип элемента в вашем методе getView и соответственно накачать правильное представление из res / layout.
Мэтью Уиллис,
1
Вы сами возвращаете его в getItemViewType.
Мэтью Уиллис
Вы делаете связь вручную в getView: if (type == 0) {/ * inflate R.layout.row_icon_on_left /} else {/ inflate R.layout.row_icon_on_right * /}
Мэтью Уиллис
75
Осторожно! getItemViewType () должен возвращать int между 0 и getViewTypeCount () - 1.
PacificSky
12

Если нам нужно показать другой тип представления в представлении списка, тогда его лучше использовать getViewTypeCount()и getItemViewType()в адаптере вместо переключения представления View.GONEи View.VISIBLEможет быть очень дорогой задачей внутри, getView()что повлияет на прокрутку списка.

Пожалуйста, проверьте это для использования getViewTypeCount()и getItemViewType()в адаптере.

Ссылка: the-use-of-getviewtypecount

kyogs
источник
Возвращение IGNORE_ITEM_VIEW_TYPE в getItemViewType () всегда будет передавать 'view' как null в getView (int position, View view, ViewGroup viewGroup), заставляя инициализировать все компоненты пользовательского интерфейса. Не является ли это плохим показателем производительности, когда в случае паттерна держателя мы можем повторно использовать существующие представления пользовательского интерфейса и можем просто переключить представление на View.GONE или View.VISIBLE в зависимости от положения.
Намрата Багервал
11

Смотри Outttt !!!!
Мне пришлось столкнуться с проблемой реализации ListViewвчерашнего дня, и сразу после прокрутки смешались два вида представлений строк. Несмотря на то, что голосование с наибольшим количеством голосов в этой теме дает хорошее общее объяснение, оно не выделило наиболее важную информацию, чтобы остановить вышеупомянутую ошибку пользовательского интерфейса, о которой я упоминал.

Вот мое объяснение:
Как getViewTypeCount()и в getItemViewType()настоящее время используется BaseAdapter«s getViewспособ выяснить , какой тип зрения следует извлечь, переработанная и вернулся. (как объяснено в верхнем ответе в теме). Но если вы не реализуете эти два метода интуитивно в соответствии с Doc Android API, вы можете столкнуться с проблемой, о которой я упоминал.

Обобщенная Руководство по осуществлению:
Для реализации нескольких типов Viewsдля ListViewстрок «S мы имеем по существу реализовать, getItemViewType()и getViewTypeCount()методы. И getItemViewType()документация дает нам Примечание следующим образом:

Примечание: целые числа должны быть в диапазоне 0до getViewTypeCount() - 1. IGNORE_ITEM_VIEW_TYPEтакже могут быть возвращены.

Таким образом, getItemViewType()вы должны вернуть значения для Типа Представления, начиная с 0, до последнего типа как (количество типов - 1). Например, допустим, у вас есть только три типа представлений? Таким образом, в зависимости от объекта данных для представления, вы можете вернуть только 0 или 1 или 2 из getItemViewType()метода, как индекс массива с нуля. И так как у вас есть три типа представлений, ваш getViewTypeCount()метод должен возвращать 3.

В любом случае, если вы вернете любые другие целочисленные значения, такие как 1, 2, 3 или 111, 222, 333 для этого метода, вы определенно можете столкнуться с вышеуказанной ошибкой пользовательского интерфейса, которую вы только что установили, не подчиняясь Документу API Android.

Если вы не получили подсказку или все еще не можете решить и нуждаетесь в дополнительной информации, пожалуйста, прочитайте мой подробный ответ в этой теме вопросов и ответов StackOverflow .

Прочитайте Документ разработчика Android для получения дополнительной информации, которую вы могли бы найти ключ непосредственно.

Надеюсь, что этот ответ может быть полезным для кого-то, чтобы сэкономить много часов !!!

Ура !!!

Рандика Вишман
источник
1
Спасибо за упоминание, IGNORE_ITEM_VIEW_TYPEчто у меня была ошибка в одном из моих ListView. Я использовал ArrayAdapter для вставки вида, состоящего из 1 изображения и 2 текстового представления. У меня был только один тип просмотра. Я пытался либо не переопределить метод getItemViewType, либо переопределить его, возвращая позицию или жестко запрограммированное целое число. Во всех случаях в моем списке возникали дубликаты со странным поведением при прокрутке (изменения дубликатов). Возвращение IGNORE_ITEM_VIEW_TYPEв метод исправило проблему. Спасибо.
Алекс
@ Алекс рад, что это было полезно для вас! :-)
Рэндика Вишман