2

У меня есть список полиморфных объектов, например List<Person>, где человек может быть сотрудником, менеджером, солдатом, роялти и т. Д. ... и я хочу отобразить список лиц в android list-view, где каждый тип лица имеет другой шаблон строки и несколько разные данные.Отображение различных типов строк в списке Android

Каков правильный способ отображения различных строк разных типов? (?)

Два плохих решений :

  1. Помещенный абстрактную getView метод внутри Person класса, так что каждый другой человек будет создавать правильный вид с помощью полиморфизма. -> Это будет смешивать модель и вид MVC - т.е. если я захочу представить список на другом экране (например, в виде таблицы), тогда он сломается.

  2. Поместите логику модели в режим просмотра внутри адаптера (унаследовано от ArrayAdapter<Person>). Например, внутри getView Я могу проверить getClass() человека и соответствующим образом заполнить правильный вид. -> Этот метод завершится длинными цепочками операторов if-else, по одному для каждого типа человека, и его необходимо будет расширить при добавлении новых типов лиц - обычно это запах плохого кода в объектно-ориентированной точке зрения. Это решение, предложенное в «How to create list with different elements and actions?»

Есть ли решение лучше, чем (2) выше?

+0

Это один из самых неприятных вопросов во всем дизайне Android UI. Мне бы хотелось увидеть больше экспертов в области андроидов. –

ответ

2

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

В пользовательском адаптере, расширить BaseAdapter и быть уверенным, что getViewTypeCount() возвращает количество различных лиц у вас есть в наборе данных, что getItemViewType(int position) возвращает правильный идентификатор для позиции в наборе данных.

Этот вопрос имеет много полезной информации по теме:

getViewTypeCount and getItemViewType methods of ArrayAdapter

+0

Хорошо, так что 3 ответа предлагают одно и то же решение - я думаю, нет лучшего способа. Я выбираю ваш ответ в основном для того, чтобы быть самым быстрым, а также для указания мне на getViewTypeCount и getItemViewType. – Iftah

+0

На самом деле это не плохой способ сделать это. Как я уже сказал, вы можете создать абстрактный метод в своем классе Person, и это также можно использовать в методе getItemViewType(). Кроме того, проверьте шаблон ViewHolder, который еще больше улучшит вашу производительность. –

+0

Это не страшное решение, но это плохо. Для добавления/удаления типов требуется изменение 3-х функций, а наличие 'getItemViewType' не синхронизируется с' getView' будет обнаружено во время выполнения, а не во время компиляции. Я предполагаю, что решение, в котором добавление поддержки нового типа строки будет просто бросать новый класс в проект и, возможно, добавить строку кода для подключения к адаптеру. – Iftah

1

создать свой собственный ListAdapter, который простирается от BaseAdapter как этот

public class YourListAdapter extends BaseAdapter implements Filterable { 
... 
} 

переопределение getViewTypeCount() и getItemViewType ()

@Override 
public int getViewTypeCount() { 
    return 2;//count of types 
} 

@Override 
public int getItemViewType(int position) { 
    return YourPersonList.get(position).getMyViewType(); 
} 

и в GetView (..)

int type = getItemViewType(position); 
switch(type){ 
case 0: 
//set the view to your layout 
break; 
case 1: 
//set the view to another layout 
break; 
} 

более или менее что-то подобное ..

// EDIT: смотреть на посте от Мичелла https://stackoverflow.com/a/17152430/1847899

1

Есть два способа, которые можно переопределить в адаптере, которые делают это проще.К ним относятся:

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

@Override 
public int getItemViewType(int pos){ 
    if (getItem(pos).type == employee) 
    return VIEW_TYPE_EMPLOYEE; 
    else if (getItem(pos).type == manager) 
    return VIEW_TYPE_MANAGER; 
} 

Используя вышеуказанные методы, вы все еще необходимо сделать некоторые работы, например, когда представление должно быть накачаны вы можете позвонить getItemViewType (позиция) из внутри GetView, но когда вы получаете который был переработан, адаптер должен дать вам правильный тип, основанный на позиции строки.

Смежные вопросы