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
@Matthew, дякую за вашу відповідь. Чи можете ви описати потік, як викликаються ці методи. Також я не розумію, як це насправді пов’язано з моїми даними в res / layout.
Євген

Немає явного контракту щодо використання цих методів. res / layout - це місце для перегляду об'єктів. Це адаптер . Ви повинні перевірити тип елемента у вашому методі getView і відповідним чином передати відповідний вигляд з res / layout.
Меттью Вілліс

1
Ви повертаєте його самостійно в getItemViewType.
Меттью Вілліс

Ви робите асоціацію вручну в getView: якщо (введіть == 0) {/ * надуйте R.layout.row_icon_on_left /} else {/ надуйте R.layout.row_icon_on_right * /}
Меттью Вілліс

75
Остерігайся! getItemViewType () повинен повернути int між 0 і getViewTypeCount () - 1.
PacificSky

12

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

Будь ласка , перевірте цей для використання getViewTypeCount()і getItemViewType()в адаптері.

Посилання: кількість-використання-getviewtypecount


Повернення IGNORE_ITEM_VIEW_TYPE в getItemViewType () завжди передасть "view" як null в getView (позиція int, view view, ViewGroup viewGroup), змушуючи ініціалізувати всі компоненти інтерфейсу користувача. Це не поганий показник продуктивності, коли у випадку шаблону власника ми отримуємо повторне використання існуючих представлень інтерфейсу, і ми можемо просто переключити подання на View.GONE або View.VISIBLE на основі позиції.
Namrata Bagerwal

11

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

Ось моє пояснення:
Як getViewTypeCount()і в getItemViewType()даний час використовується BaseAdapter«s getViewспосіб з'ясувати , який тип зору слід витягти, перероблена і повернувся. (як пояснено у верхній відповіді в потоці). Але якщо ви не реалізуєте ці два способи інтуїтивно відповідно до Android API Doc, то ви можете потрапити в проблему, про яку я згадав.

Узагальнена Керівництво по здійсненню:
Для реалізації декількох типів 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 для цього методу, ви, безумовно, можете відчути вищезгадану помилку інтерфейсу, яку ви просто помістили, не підкоряючись Документу Android API.

Якщо ви не отримали ключ або не міг ще вирішити і потрібна додаткова інформація , будь ласка , прочитайте мій докладну відповідь в цій StackOverflow Q & A нитку .

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

Сподіваюся, що ця відповідь може бути корисною для когось там, щоб заощадити багато годин !!!

Ура !!!


1
Дякуємо, що згадали, IGNORE_ITEM_VIEW_TYPEщо в одному зі моїх ListView з'явилася помилка. Я використав ArrayAdapter, щоб вставити представлення, що складається з 1 зображення та 2 подання тексту. У мене був лише один тип перегляду. Я намагався або не заміняти метод getItemViewType, або переосмислювати його, повертаючи позицію або жорстко закодоване ціле число. У всіх випадках у моєму списку у мене були дублікати із незвичайною поведінкою під час прокрутки (зміни дублікатів). Повернувшись IGNORE_ITEM_VIEW_TYPEдо методу, виправлено проблему. Дякую.
Олексій

@ Алекс радий, що тобі було корисно! :-)
Рандіка Вішман
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.