2013-08-05 3 views
2
public View getView(int index, View view, ViewGroup parent){ 
    if (view == null) { // for the first time, inflate the view 
     LayoutInflater inflater = 
      LayoutInflater.from(parent.getContext()); 
     view = inflater.inflate(
      R.layout.time_list_item, parent, false); 
    } 
    /** 
    * The layout under consideration has two TextViews in it 
    * one to display the time and other to display some text. 
    */ 
    TimeRecord time = times.get(index); 
    timeTextView.setText(time.getTime()); 
    TextView timeTextView = (TextView) 
    view.findViewById(R.id.time_view); 
    notesTextView.setText(time.getNotes()); 
    TextView notesTextView = (TextView) 
    view.findViewById(R.id.notes_view); 

    return view; 
} 

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

Эти возвращенные виды будут отображаться в ListView. Если я когда-либо верну только один View, который я заново заполняю новыми данными, как данные будут правильно отображаться? Как может быть несколько записей?
Другими словами, я не просто возвращаю один вид и ожидаю увидеть несколько записей ListView? Разве это не значит, что я возвращаю новый Views?

+0

http://android.amberfog.com/?p=296 –

ответ

3

Как GetView() работает в пользовательском адаптере?

Метод getView() вызывается так много раз, как число строк e.q. каждая строка имеет собственный вид.

Теперь это «повторное использование» меня сбивает с толку.

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

Для этой цели используется шаблон-образец держателя. Это простой произвольный объект, который содержит ссылки на дочерние представления каждой строки.

Вы можете реализовать это нравится:

public class RowHolder { 

    private View row; 

    // childs widgets in row 
    private TextView name; 

    public RowHolder(View row) { 
     this.row = row; // row in ListView (in your case) 
    } 

    public TextView getName() { 
     if (name == null) { 
     name = (TextView) row.findViewById(<id>); 
     } 
     return name; 
    } 

    ... 
} 

И обычай:

LayoutInflater inflater; 
RowHolder holder = null; 

// row created first time 
if (convertView == null) { 
    convertView = inflater.inflate(<rowXMLLayout>, null, false); 
    holder = new RowHolder(convertView); // adding row to arbitrary obj 
    convertView.setTag(holder) // adding this obj to row at position 
} 
else { 
    // recycling started 
    holder = (RowHolder) convertView.getTag(); 
} 


// updating rows 
holder.getName().setText(<value?>); 
... 
+0

так и в случае пользовательского 'ExpandableListViewAapter 'метод, который я опубликовал, не будет работать. Это должно быть ... изменено :) –

+0

@LittleChild вы должны получить больше «эффективности». – Sajmon

1

Это поведение в ListView с именем Recycling, вы можете получить более подробную информацию о How ListView's recycling mechanism works и View Recycling in ListView

+0

Спасибо, сообщение в блоге на f2.prateek действительно помогло мне понять :) –

+0

Рад слышать, что;) –

1

Так ListView использует свой собственный адаптер таким образом:

  • Он раздувает взгляды, которые видны + несколько, которые находятся вне экрана, до будут подготовлены для показа их позже.
  • Он раздувает представления, вызывая метод getView().
  • Результаты состоят в том, что представление сохраняется в массив слабых ссылок внутри ListView - смысл может быть удален из него сборщиком мусора, когда в приложении заканчивается память.

Преимущество в том, что при правильном повторном использовании RECYCLED VIEW в вашем getView команда inflate() будет вызываться иногда только один раз (но не для каждого элемента списка, когда это необязательно). И это раздувание - это то, что мы хотим опустить, потому что оно очень медленное.

И этот массив имеет столько же входов, сколько ваш пользовательский адаптер возвращается в getViewTypeCount(). В простых списках это будет всего лишь 1.Вот почему при выполнении этой рециркуляции в getView (int index, View recycledView, родительская группа ViewGroup) вы будете получать в качестве параметра один и тот же recycledView каждый раз, который вы должны использовать USE = опустить другое надувание и изменять его свойства, такие как textViews, images и т. Д. поэтому он содержит вещи, которые вы хотите. Другими словами, каждый элемент списка не выглядит одинаковым, но похож на него, поскольку он имеет одинаковый макет (буквально тот же файл макета и тот же макет, что и поля, ширина и т. Д.).

Если вы используете в Listview несколько взгляды, означающие, как только вы надуваете 1 вид, в другое время разные. Десять вы должны переопределить getViewTypeCount() и getItemViewType(), чтобы Listview знал, какой индекс списка должен получить, какой вид.

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