Что такое работа 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).