Что такое работа setTag и getTag в шаблоне ViewHolder?

У меня есть простой фрагмент кода для реализации пользовательского списка.

Мой код выглядит следующим образом:

WeatherAdapter.java:

public class WeatherAdapter extends ArrayAdapter<weather>{

    Context mcontext; 
    int mlayoutResourceId;    
   weather mdata[] = null;
   View row;

    public WeatherAdapter(Context context, int layoutResourceId, weather[] data) {
        super(context, layoutResourceId, data);
        mlayoutResourceId = layoutResourceId;
       mcontext = context;
        mdata = data;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
      row = convertView;
        WeatherHolder holder = null;

        if(row == null)
        {
            LayoutInflater inflater = ( (Activity) mcontext).getLayoutInflater();
            row = inflater.inflate(mlayoutResourceId, parent, false);

            holder = new WeatherHolder(row);


            row.setTag(holder);

        }
        else
        {
            holder = (WeatherHolder)row.getTag();
        }

        weather w = mdata[position];
        holder.txtTitle.setText(w.mtitle);
        holder.imgIcon.setImageResource(w.micon);

        return row;
    }

WeatherHolder.java

class WeatherHolder
    {
        ImageView imgIcon;
        TextView txtTitle;


    public WeatherHolder(View v){

          imgIcon = (ImageView)row.findViewById(R.id.imgIcon);
          txtTitle = (TextView)row.findViewById(R.id.txtTitle);

    }
    }
}

Я видел так много ответов на SO и других сайтах, и я понял механизм рециркуляции списка.

Я также понял, что из зрителя мы можем удерживать дочерние представления в адаптере, и нам не нужно много раз называть findViewById(). Итак, это для оптимизации.

Но у меня есть только путаница в методах setTag(holder) и getTag(). Из этого вопроса, я узнал, что он предназначен для создания пары ключ-значение на нескольких объектах, чтобы мы могли легко получить к ним доступ. Но я не понимаю, почему они здесь требуются... потому что у нас нет нескольких объектов-держателей... только мы должны каждый раз менять переменные-держатели. можно ли здесь закодировать без использования setTag и getTag?

может ли кто-нибудь лучше объяснить, что делать setTag и getTag здесь?

Ответ 1

tag - это механизм, позволяющий вашему views запомнить что-то, что может быть object a integer a string или что угодно.

поэтому, когда ваш ListView будет создан в первый раз, ваш convertView будет null. поэтому создайте новый convertView и поместите все references из objects этого row в viewHolder. затем сохраните viewHolder в памяти этого convertView (setTag). Android берет ваш convertView и помещает его в pool в recycle и passes снова вам. но его pool может не хватить convertViews, поэтому он снова передает новый convertView thats null. так что история повторяется до тех пор, пока pool of Android не будет заполнен. после этого Android берет convertView из своего пула и передает его вам. вы обнаружите, что это не null, поэтому вы спрашиваете, где мой объект references, который я дал вам в первый раз? ( getTag), чтобы вы получили их и делали все, что захотите.

Подробнее о линии ниже

but its pool may not have enough convertViews so it again passes a new convertView thats null

android pool пуст, когда будет создан ваш ListView. поэтому для первого элемента вашего ListView он отправляет вам convertView, который должен отображаться. после этого Android сохраняет его в pool, поэтому его pool теперь содержит только один convertView. для вашего второго элемента вашего ListView, который собирается создать андроид, он не может использовать свой пул, потому что на самом деле он имеет один элемент, и этот элемент является вашим первым элементом, и он отображается прямо сейчас, поэтому ему нужно передать еще один convertView, этот процесс повторяется до тех пор, пока Android не найдет convertView в своем pool, который теперь не отображается и передает его вам.

Android раздувает каждую строку до тех пор, пока экран не заполнится после этого, когда вы прокрутите список, в котором он использует держатель.

Ответ 2

Давайте посмотрим в другой перспективе:

enter image description here

Давайте предположим, что Вертолет - это " row", а веревка - " setTag", а автомобиль ниже " WeatherHolder", но пилот вертолета находится внутри этого автомобиля, и он/она управляет вертолетом с помощью "WIRED REMOTE".

Когда вы сокращаете веревку, которая является "setTag", вертолет все еще летает, но пилот больше не может контролировать его, так как пилот падает в землю, что означает, что пилот теперь мертв! (В java, когда потеря объекта ссылается на сборщик мусора, он будет собирать и освобождать память).

Когда вы не разместили или не привязали веревку к машине, пока вертолет уже летает там, где сидит пилот, вы можете потерять контроль над вертолетом, потому что используете "WIRED REMOTE".

Я надеюсь, что эта помощь:).

Ответ 3

Но я не понимаю, зачем они здесь нужны... потому что у нас нет нескольких объектов-держателей

Здесь вы ошибаетесь - для каждого представления есть один держатель (он же видимый или кэшированный элемент ListView).