我有一个简单的代码段,用于实现自定义列表视图。
我的代码如下:
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和其他网站上看到了很多答案,我理解了listview的回收机制。
我也理解,从viewholder,我们可以在适配器中保存子视图,我们不必多次调用findViewById()
。所以,它是为了优化。
但我只有setTag(holder)
和getTag()
方法中的混淆。 From this question,我发现它是为多个对象创建一个键值对,以便我们可以轻松访问它们。但是,我不明白为什么在这里需要它们...因为,我们没有多个持有者对象......只有我们每次都必须更改持有者的变量。我们可以在此处进行编码而不使用setTag
和getTag
吗?
任何人都可以更好地解释setTag
和getTag
做什么&#34;这里&#34 ;?
答案 0 :(得分:24)
tag
是一种机制,可让您views
记住某些内容,可能是object
integer
个string
或您喜欢的任何内容。
所以,当您的ListView
首次创建convertView
为null
时。因此,您需要创建一个新的convertView
,并将references
objects
的{{1}} row
放入viewHolder
。然后将viewHolder
保存到convertView
( setTag )的内存中。 Android
会将convertView
移至pool
至recycle
,passes
将其再次发送给您。但其pool
可能没有足够的convertViews
,因此它会再次传递convertView
null
。所以故事再次重复,直到pool
的{{1}}被填满。之后android
从其池中获取android
并将其传递给您。你会发现它不是convertView
所以你问我第一次给你的对象null
在哪里? ( getTag )所以你会得到那些并做你喜欢的事。
在下面的详细说明
references
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
。对于你要创建android的convertView
的第二项不能使用它的池,因为它实际上有一个元素,那个元素是你的第一个项目,它现在正在显示,所以它必须传递另一个{ {1}}。此过程会一直重复,直到listView
在convertView
中找到android
现在未显示的convertView
并将其传递给您。
当你滚动使用持有者的列表时,Android会对每一行进行充气,直到屏幕填满为止。
答案 1 :(得分:16)
让我们从不同的角度看:
让我们想象 Helicopter 是&#34; 行&#34;而绳是&#34; setTag &#34;下面的汽车是&#34; WeatherHolder &#34;,但直升机的飞行员在那辆汽车内,他/她是管理控制直升机的人a&#34; WIRED REMOTE&#34;。
当你切断绳索时,#34; setTag&#34;直升机仍在飞行,但飞行员无法控制它,因为飞行员在地面下降,这意味着飞行员现在已经死了! (在java中,当一个对象丢失它的引用时,垃圾收集器将收集该内容并从内存中释放出来。)
当直升机即将飞行在飞行员所在的地方时,你没有将绳子放置或附着在汽车上 - 你可能会失去对直升机的控制,因为你正在使用&#34; WIRED REMOTE&#34;。
我希望这有帮助:)。
答案 2 :(得分:2)
但是,我不明白为什么在这里需要它们...因为,我们没有多个持有者对象
这是你错的地方 - 每个视图都有一个持有者(也就是可见或缓存的ListView条目)。