В чем разница между двумя видами реализации getView()?

#android #listview

#Android #просмотр списка

Вопрос:

Кто-нибудь может, пожалуйста, объяснить, в чем разница между двумя видами реализации getView ()?

Первый просто проверяет, имеет ли convertView значение null; если оно равно null, создайте новый объект View. Затем установите вложенные представления с соответствующими значениями.

 @Override
public View getView(int position, View convertView, ViewGroup parent) 
{           
    if(convertView == null)
    {
        LayoutInflater inflater = context.getLayoutInflater();
        convertView = inflater.inflate(R.layout.itemlayout, null, true);
    }   

    ImageView image = (ImageView) convertView.findViewById(R.id.icon);
    TextView text = (TextView) convertView.findViewById(R.id.name);     

    MyItem item = items[position];
    text.setText(item.name);
    if("male".equals(item.gender))
    {
        image.setImageResource(R.drawable.male);
    }
    else if("female".equals(item.gender))
    {
        image.setImageResource(R.drawable.female);
    }

    return convertView;
}
  

Второй — это так называемый шаблон «ViewHolder». Многие разработчики говорят, что этот метод экономит много памяти и процессорного времени. Но первая реализация также проверяет существование convertView. Разве первый метод не экономит немного памяти? Кто-нибудь может объяснить разницу между этими двумя реализациями более глубоко и понятно? Большое спасибо.

 @Override
public View getView(int position, View convertView, ViewGroup parent) 
{       
    ViewHolder holder;

    View itemView = convertView;
    if(itemView == null)
    {
        LayoutInflater inflater = context.getLayoutInflater();
        itemView = inflater.inflate(R.layout.itemlayout, null, true);
        holder = new ViewHolder();
        holder.image = (ImageView) itemView.findViewById(R.id.icon);
        holder.text = (TextView) itemView.findViewById(R.id.name);
        itemView.setTag(holder);
    }
    else
    {
        holder = (ViewHolder) itemView.getTag();
    }

    MyItem item = items[position];
    holder.text.setText(item.name);
    if("male".equals(item.gender))
    {
        holder.image.setImageResource(R.drawable.male);
    }
    else if("female".equals(item.gender))
    {
        holder.image.setImageResource(R.drawable.female);
    }

    return itemView;
}
  

Ответ №1:

Второй шаблон создает статический экземпляр ViewHolder и прикрепляет его к элементу view при первой загрузке, а затем он будет извлекаться из этого тега view при будущих вызовах

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

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

Комментарии:

1. Речь идет не только о findViewById(), хотя это наиболее распространенный вариант использования. ViewHolder может и должен также использоваться для хранения временных структур данных, чтобы избежать выделения памяти в getView(). Хороший пример можно найти здесь: goo.gl/NzgTt и goo.gl/d4vvo ViewHolder содержит буфер символов, чтобы избежать выделения при получении данных от курсора.

Ответ №2:

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