我对自定义数组适配器的getView方法中的视图回收有一个不明确的问题。
我理解元素是可以重用的,但是我怎么知道在if语句的第一部分中要实现什么,以及在第二部分中实现什么?
现在我有以下代码。由于删除了语句的第二部分中的代码,我得出了这个问题,这导致了前9个元素的列表,这些元素重复了多次而不是所有元素。我真的不知道究竟是什么造成了这个......
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
if (row == null) {
LayoutInflater inflater = ((Activity) context).getLayoutInflater();
row = inflater.inflate(layoutResourceId, parent, false);
title = getItem(position).getTitle();
size = calculateFileSize(position);
txtTitle = (TextView) row.findViewById(R.id.txtTitle);
tvFileSize = (TextView) row.findViewById(R.id.tvFileSize);
txtTitle.setText(title);
tvFileSize.setText(size);
} else {
title = getItem(position).getTitle();
size = calculateFileSize(position);
txtTitle = (TextView) row.findViewById(R.id.txtTitle);
tvFileSize = (TextView) row.findViewById(R.id.tvFileSize);
txtTitle.setText(title);
tvFileSize.setText(size);
}
return row;
}
答案 0 :(得分:15)
这很容易。第一次没有创建行,所以你必须给它们充气。之后,Android操作系统可能决定回收您已经膨胀并且不再可见的视图。这些已经被夸大并传递到convertView参数,所以你要做的就是安排它来显示新的当前项目,例如将正确的值放入各种文本字段。
简而言之,在第一部分中你应该执行膨胀并填充值,在第二部分if(if convertView != null
)中你应该只覆盖该字段,因为,鉴于视图已被回收,textviews包含旧项目的价值。
答案 1 :(得分:13)
我理解元素是可以重用的,但是我怎么知道在if语句的第一部分中要实现什么,以及在第二部分中实现什么?
一旦掌握了它,组织就会非常简单:
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
/* This is where you initialize new rows, by:
* - Inflating the layout,
* - Instantiating the ViewHolder,
* - And defining any characteristics that are consistent for every row */
} else {
/* Fetch data already in the row layout,
* primarily you only use this to get a copy of the ViewHolder */
}
/* Set the data that changes in each row, like `title` and `size`
* This is where you give rows there unique values. */
return convertView;
}
有关ListView的RecycleBin如何工作的详细解释以及为什么ViewHolders很重要,请观看Turbo Charge your UI,这是Android的主要ListView程序员的Google I / O演示。
答案 2 :(得分:5)
您想在ViewHolder
中创建MainActivity
课程。像
static class ViewHolder
{
TextView tv1;
TextView tv2;
}
然后在getView
中,第一次从Views
中的xml获取if
,然后在else
View rowView = convertView;
if (rowView == null)
{
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
rowView = inflater.inflate(R.layout.layout_name_to_inflate, parent, false);
holder = new ViewHolder();
holder.tv1= (TextView) rowView.findViewById(R.id.textView1);
holder.tv2 = (RadioGroup) rowView.findViewById(R.id.textView2);
rowView.setTag(holder);
}
else
{
holder = (ViewHolder) rowView.getTag();
}
答案 3 :(得分:4)
我建议您使用View holder和convertview模式来创建listView,因为它会更有效。Here可以很好地解释它如何与重用策略一起使用。这将回答您关于再循环如何工作的问题。如果您想参考代码示例,我可以在GitHub上找到它。
希望这有帮助。
答案 4 :(得分:1)
问题的最后一部分,如果没有效果的图片我真的无法掌握,但第一部分“在if语句的第一部分实现什么,第二部分是什么”我认为我已经发现这个实现很常见。
您首先会找到视图引用并将它们存储到静态类ViewHolder
,然后将其附加到新的膨胀视图的标记。由于listview会回收视图并传递convertView
getView
,因此您可以从convertView
的标记中获取ViewHolder,这样您就不必再次找到引用(这极大地提高了性能)并使用给定位置的对象更新视图数据。
从技术上讲,您并不关心视图的位置,因为您所关心的只是对您需要更新的视图的引用,这些视图保存在ViewHolder中。
@Override
public View getView(int position, View convertView, ViewGroup container) {
ViewHolder holder;
Store store = getItem(position);
if (convertView == null) {
convertView = mLayoutInflater.inflate(R.layout.item_store, null);
// create a holder to store references
holder = new ViewHolder();
// find references and store in holder
ViewGroup logoPhoneLayout = (ViewGroup) convertView
.findViewById(R.id.logophonelayout);
ViewGroup addressLayout = (ViewGroup) convertView
.findViewById(R.id.addresslayout);
holder.image = (ImageView) logoPhoneLayout
.findViewById(R.id.image1);
holder.phone = (TextView) logoPhoneLayout
.findViewById(R.id.textview1);
holder.address = (TextView) addressLayout
.findViewById(R.id.textview1);
// store holder in views tag
convertView.setTag(holder);
} else {
// Retrieve holder from view
holder = (ViewHolder) convertView.getTag();
}
// fill in view with our store (at this position)
holder.phone.setText(store.phone);
holder.address.setText(store.getFullAddress());
UrlImageViewHelper.setUrlDrawable(holder.image, store.storeLogoURL,
R.drawable.no_image);
return convertView;
}
private static class ViewHolder {
ImageView image;
TextView phone;
TextView address;
}