我想知道为什么ListView或GridView在滚动期间使用了旧项目?我有一个列表视图,我在列表视图中显示了500多种产品。每个列表项有4列,最后一列是ImageView,显示状态为活动或非活动。每当我将ImageView标记为活动时,在定期滚动后,每个项目都会自动将其ImageView更改为活动状态。
假设我点击了第6个项目并使其ImageView处于活动状态,那么在滚动期间我看到第12,18,24等也被更改为活动
答案 0 :(得分:1)
为了优化滚动体验,ListView
和GridView
将重复使用项目视图,以避免为每个列表项目充气/实例化视图。
这就是为什么getView
的{{1}}类型参数名为View
的原因。当convertView
为空时,您需要为该项目的新视图充气。当它不为空时,这意味着您可以重新使用此视图以避免通货膨胀的开销。
缺点是这个“循环”项目视图从上次显示时会有垃圾,你必须重置视图中的所有内容以匹配列表项。
新Android开发人员犯的一个常见错误是没有视图中所有内容的模型表示。例如,如果您的列表项可以显示活动或非活动状态,那么列表项的模型应该具有convertView
属性boolean
。
列表的模型必须在任何给定时间具有列表的整个当前状态,以便只要mActive
决定需要重新显示其列表项,就可以重新创建它。
所以你需要做的事情基本上是四件事:
将属性添加到列表项模型中:
ListView
创建用于更改状态的适配器方法。例如:
boolean mActive; // this can be private with getter/setter
在此处致电 public void toggleItemActive(int position) {
mListItem.get(position).mActive = ! mListItem.get(position).mActive;
notifyDataSetChanged();
}
非常重要。
在notifyDataSetChanged()
覆盖中使用此属性:
getView
从事件处理程序设置属性:
imageView.setImageResource(item.mActive ? R.drawable.active : R.drawable.inactive); // or however you are doing it
现在,您的 listView.setOnItemClickListener(new OnItemClickListener) {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
MyAdapter adapter = (MyAdapter) parent.getAdapter();
adapter.toggleItemActive(position);
}
});
会正确显示您的列表项。
答案 1 :(得分:0)
我认为您在自定义适配器的getView()方法中使用了viewholder。当您使用视图持有者时,您将重用视图。从您的描述看起来,您的设备可以一次只列出6个列表项。因此,第6个,第12个(第6个位置+ 6个大小的屏幕),第18个(第12个位置+ 6个大小的屏幕),第24个等都将使用相同的视图。因此,当第6项改变时,相关的第12,第18,第24项等项目也将被改变。