Настройка адаптера списка - Как не повторить ресурс макета элемента списка? - PullRequest
0 голосов
/ 02 марта 2012

Я сделал ListView с ArrayAdapter.Оно работает.Но мне пришлось дважды поместить идентификатор ресурса для макета элемента: в определении адаптера и в getView, в случае, когда параметр View имеет значение null.

// --------------------------------------------here is the FIRST use
lvShows.setAdapter(new ArrayAdapter<TvShow>(this, R.layout.show_row, allKnownShows) {
    @Override
    public View getView(int position, final View rowView, ViewGroup parent) {
        LinearLayout showView;
        if (rowView == null) {

            // --------------------------------- here is the SECOND use
            showView = (LinearLayout) inflater.inflate(R.layout.show_row, parent, false);
        }
        else {
            showView = (LinearLayout) rowView;
        }
        ((TextView) showView.getChildAt(0)).setText(time));
        ((TextView) showView.getChildAt(1)).setText(name);
        return showView;
    }
});

Такой стиль отвратителен, конечно.Не могли бы вы посоветовать, что я не так понимаю и как я могу использовать ресурс только один раз?

Если я создаю новый ArrayAdapter, я устанавливаю идентификатор макета, он должен это знать и каким-то образом использовать.Как я мог достичь этого?Или лучше я ожидал бы, что Адаптер создаст представления элементов автоматически.Опять же - как я могу его использовать?

Что делает ArrayAdapter с тем ресурсом, который мы передаем ему при создании нового?Все его конструкторы берут ресурс элемента, и мы управляем этим ресурсом и раздуваем его «вручную».Это не эффективный способ.

Ответы [ 2 ]

2 голосов
/ 02 марта 2012

Я посмотрел исходный код ArrayAdapter, и он уже выполняет весь этот процесс создания представления:

// citation from public class ArrayAdapter<T>
private View createViewFromResource(int position, View convertView, ViewGroup parent,
        int resource) {
    View view;
    TextView text;
    if (convertView == null) {
        view = mInflater.inflate(resource, parent, false);
    } else {
        view = convertView;
    }

Итак, мы должны просто использовать его:

lvShows.setAdapter(new ArrayAdapter<TvShow>(this, 
                                            R.layout.show_row, 
                                            R.id.nameField, 
                                            allKnownShows){
public View getView(int position, final View convertView, ViewGroup parent) {
    LinearLayout showView = (LinearLayout) super.getView(position,  convertView, parent);

    setAnythingForItem(showView);

    return showView;
}

Внимание: мы изменили конструктор!

ArrayAdapter позволяет использовать макет элемента без TextView.Но если это не сам TextView, он должен иметь его, и идентификатор этого самого внутреннего поля TextView должен быть передан конструктору в качестве третьего параметра.ArrayAdapter нужно, чтобы он был установлен, чтобы записывать туда Strings, если подключенный к нему массив имеет элементы String.

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

2 голосов
/ 02 марта 2012

Вы можете переопределить конструктор ArrayAdapter и вызвать super:

public ArrayAdapter<T>(Context context, TheDataType data) {
   super(context, R.layout.show_row, data);
 }

И сохранить идентификатор в переменной-члене ArrayAdapter. Избегайте «пользователя» адаптера, чтобы знать, какой вид необходим для адаптера.

Или вы можете использовать BaseAdapter.

...