使用视图持有者时,listView 中的行回收如何工作?
How does the recyclying of rows in an listView work when working with a view holder?
我已经为我的 ListView 行定义了一个 ViewHolder,如下所示:
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
class ViewHolder
{
ImageView icon=null;
TextView size=null;
ViewHolder(View row)
{
this.icon=(ImageView)row.findViewById(R.id.icon);
this.size=(TextView)row.findViewById(R.id.size);
}
}
和适配器 class 的 getView()
方法如下所示:
@Override
public View getView(int position, View convertView,
ViewGroup parent) {
View row=super.getView(position, convertView, parent);
ViewHolder holder=(ViewHolder)row.getTag();
if (holder==null) {
holder=new ViewHolder(row);
row.setTag(holder);
}
if (getModel(position).length()>4) {
holder.icon.setImageResource(R.drawable.delete);
}
else {
holder.icon.setImageResource(R.drawable.ok);
}
holder.size.setText(String.format(getString(R.string.size_template), items[position].length()));
return(row);
}
现在我的问题是:
Viewreturn上的getTag()
调用在什么情况下会为空?
row.setTag(holder)
有什么作用以及它如何重新初始化 ViewHolder?
ListView 中的视图回收是如何工作的?getTag()
和 setTag()
在使用适配器时如何帮助我们解决这个问题?
我对工作机制有点迷惑,搜索了Stack Overflow也没有找到任何结果。
这是一个很好的question.So 为了了解标签在适配器中的行为,我们需要了解 listView 中回收流程的实际行为。
Tag
是一个让我们的 views
记住一些东西的小工具,它可以是一个对象,一个整数或任何其他东西,所以当我们的 ListView
去创建第一个当时 convertView
是 null
,所以我们创建一个新的 convertView
并将我们对 row
objects
的所有引用放在 viewHolder
,然后将我们的 viewHolder
保存到那个 convertView
(setTag
) 的内存中。 Android 获取我们的 convertView
并将其放入其池内存中以回收它并再次传递给我们。但是它的池内存可能没有足够的 convertViews
所以它再次传递一个新的 convertView
那就是 null
。所以再次重复这个故事,直到 android 的池被填满。之后 android
从其池中取出一个 convertView
并将其传递给我们。你会发现它不是空的,所以你问它我第一次使用 getTag()
给你的对象引用在哪里,这样你就可以得到它们并做任何你喜欢的事情。
这是list ViewHolder的处理流程,如果你想了解更多关于setTag()和getTag()的知识,我给你举个例子:
假设您正在创建一堆具有类似行为的视图,例如:
button1.setOnClickListener(new OnClickListener ... );
button2.setOnClickListener(new OnClickListener ... );
然后您将重写方法 onClick(),例如:
private void onClick(View view) {
doAction(0); // here 0 for button 1 and 1 for button 2.
}
这是因为您在 onclick()
方法中只有一个参数 View,您可以使用 setTag() 来更改其行为,使用值“0”和“1”来访问不同的按钮:
只需添加
button1.setTag(0);
button2.setTag(1);
现在,您可以通过使用函数 getTag() 将标签附加到视图来为每个按钮使用相同的 OnClickListener:
listener = new OnClickListener() {
@Override
public void onClick(View view) {
doAction(view.getTag());
}
};
这是因为您使用 setTag()
方法将视图放入池内存,然后相应地从池中获取这些视图。
我已经为我的 ListView 行定义了一个 ViewHolder,如下所示:
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
class ViewHolder
{
ImageView icon=null;
TextView size=null;
ViewHolder(View row)
{
this.icon=(ImageView)row.findViewById(R.id.icon);
this.size=(TextView)row.findViewById(R.id.size);
}
}
和适配器 class 的 getView()
方法如下所示:
@Override
public View getView(int position, View convertView,
ViewGroup parent) {
View row=super.getView(position, convertView, parent);
ViewHolder holder=(ViewHolder)row.getTag();
if (holder==null) {
holder=new ViewHolder(row);
row.setTag(holder);
}
if (getModel(position).length()>4) {
holder.icon.setImageResource(R.drawable.delete);
}
else {
holder.icon.setImageResource(R.drawable.ok);
}
holder.size.setText(String.format(getString(R.string.size_template), items[position].length()));
return(row);
}
现在我的问题是:
Viewreturn上的
getTag()
调用在什么情况下会为空?row.setTag(holder)
有什么作用以及它如何重新初始化 ViewHolder?ListView 中的视图回收是如何工作的?
getTag()
和setTag()
在使用适配器时如何帮助我们解决这个问题?
我对工作机制有点迷惑,搜索了Stack Overflow也没有找到任何结果。
这是一个很好的question.So 为了了解标签在适配器中的行为,我们需要了解 listView 中回收流程的实际行为。
Tag
是一个让我们的 views
记住一些东西的小工具,它可以是一个对象,一个整数或任何其他东西,所以当我们的 ListView
去创建第一个当时 convertView
是 null
,所以我们创建一个新的 convertView
并将我们对 row
objects
的所有引用放在 viewHolder
,然后将我们的 viewHolder
保存到那个 convertView
(setTag
) 的内存中。 Android 获取我们的 convertView
并将其放入其池内存中以回收它并再次传递给我们。但是它的池内存可能没有足够的 convertViews
所以它再次传递一个新的 convertView
那就是 null
。所以再次重复这个故事,直到 android 的池被填满。之后 android
从其池中取出一个 convertView
并将其传递给我们。你会发现它不是空的,所以你问它我第一次使用 getTag()
给你的对象引用在哪里,这样你就可以得到它们并做任何你喜欢的事情。
这是list ViewHolder的处理流程,如果你想了解更多关于setTag()和getTag()的知识,我给你举个例子:
假设您正在创建一堆具有类似行为的视图,例如:
button1.setOnClickListener(new OnClickListener ... );
button2.setOnClickListener(new OnClickListener ... );
然后您将重写方法 onClick(),例如:
private void onClick(View view) {
doAction(0); // here 0 for button 1 and 1 for button 2.
}
这是因为您在 onclick()
方法中只有一个参数 View,您可以使用 setTag() 来更改其行为,使用值“0”和“1”来访问不同的按钮:
只需添加
button1.setTag(0);
button2.setTag(1);
现在,您可以通过使用函数 getTag() 将标签附加到视图来为每个按钮使用相同的 OnClickListener:
listener = new OnClickListener() {
@Override
public void onClick(View view) {
doAction(view.getTag());
}
};
这是因为您使用 setTag()
方法将视图放入池内存,然后相应地从池中获取这些视图。