您走在正确的轨道上,这里有一些信息可能有助于更了解 ListViews 的工作原理:
该方法的简单实现getView()
有两个目标。首先是膨胀要显示在列表中的视图。第二个是用需要显示的数据填充视图。
正如您所说,ListViews 重新利用了组成列表的视图。这有时被称为视图回收。这样做的原因是可扩展性。考虑一个包含 1000 项数据的 ListView。视图会占用大量空间,膨胀 1000 个视图并将它们全部保存在内存中是不可行的,因为这可能会导致性能下降或可怕的OutOfMemoryException
. 为了保持 ListView 的轻量级,Android 使用该getView()
方法将 View 与底层数据结合起来。当用户上下滚动列表时,任何从屏幕上移出的视图都会被放置在视图池中以供重复使用。的convertView
参数getView()
来自这个列表。最初,这个池是空的,所以 null 视图被传递给getView()
. 因此,getView 的第一部分应该检查是否convertView
之前已经膨胀了。此外,您需要配置convertView
所有列表项共有的属性。该代码将如下所示:
if(convertView == null)
{
convertView = new TextView(context);
convertView.setTextSize(28);
convertView.setTextColor(R.color.black);
}
实现的第二部分getView()
查看列表的基础数据源并配置视图的这个特定实例。例如,在我们的测试列表中,我们可能有一个 Array of Strings 来设置视图的文本,并希望将标签设置为该视图的 Data 中的当前位置。我们根据参数知道我们正在处理列表中的哪个项目position
。接下来是这个配置。
String listText = myListStringsArray[position];
((TextView)convertView).setText(listText);
convertView.setTag(position);
这使我们能够最大限度地减少我们花费在膨胀/创建新视图上的时间,这是一项昂贵的操作,同时仍然能够快速配置每个视图以进行显示。将它们放在一起,您的方法将如下所示:
@Override
public View getView(int position, View convertView, ViewGroup)
{
if(convertView == null)
{
convertView = new TextView(context);
//For more complex views, you may want to inflate this view from a layout file using a LayoutInflator, but I'm going to keep this example simple.
//And now, configure your View, for example...
convertView.setTextSize(28);
convertView.setTextColor(R.color.black);
}
//Configure the View for the item at 'position'
String listText = myListStringsArray[position];
((TextView)convertView).setText(listText);
convertView.setTag(position);
//Finally, we'll return the view to be added to the list.
return convertView;
}
如您所见,不需要 ViewHolder,因为操作系统会为您处理它!视图本身应被视为临时对象,它们需要保留的任何信息都应使用您的基础数据进行管理。
还有一点需要注意的是,操作系统对放置在池中的视图没有任何作用,它们保持原样,包括它们填充的任何数据或对它们所做的更改。一个良好实现的getView()
方法将确保底层数据跟踪视图状态的任何变化。例如,如果您将 TextView 的文本颜色更改为红色 onClick,则当该视图被回收时,文本颜色将保持红色。在这种情况下,文本颜色应链接到一些基础数据,并在if(convertView == null)
每次getView()
调用时设置在条件之外。(基本上,所有 convertViews 通用的静态设置都发生在基于当前列表项的有条件的动态设置内,之后发生用户输入)希望这会有所帮助!
已编辑 - 使示例更简单并清理了代码,谢谢 Sam!