我多次遇到过这个问题,通过快速搜索很容易找到许多类似的问题。有时,ListView行布局上的动态更改也会影响其他行,有时则不会。
作为这个问题的解决方案,我通常会跟踪列表中的整个项目集,每次更改时,我都会重置列表中的所有项目。
Ex:如果我有一个包含TextViews和复选框的列表,我必须保留一个布尔数组,指示每个复选框的状态,并在我的getView()覆盖上,我重置基于该数组的所有复选框。
这是预期的吗?我可以找到关于这个问题的几个问题,所有的解决方案似乎与我的相似。
现在我遇到一个问题,我需要在一个非常长的列表中一次跟踪几个项目(背景,复选框和文本)。我想知道这个问题是否还有其他方法。
答案 0 :(得分:2)
这是Android中ListViews的预期行为。您使用基础数据填充列表中的视图的方法正在按计划进行。
Android在创建ListView时使用了一种称为View Recycling的技术,因为与使用数据填充视图相比,膨胀视图是一项密集型操作。 Android通过仅创建用户在屏幕上看到的视图,将通货膨胀降至最低(在程序员的帮助下)。当用户向上滚动列表时,移出屏幕的视图将被放置在池中,以供将要显示的新项目重用。来自此池的视图将作为第二个参数传递给getView
。此视图将保留与从列表中弹出的确切状态,因此由getView方法擦除清除任何旧数据的状态,并根据基础数据中的新状态重新填充它。以下是getView()
的实现应具有的结构示例:
@Override
public View getView (int position, View convertView, ViewGroup parent)
{
//The programmer has two responsibilities in this method.
//The first is to inflate the view, if it hasn't been
//convertView will contain a view from the aforementioned pool,
// but when first creating the list, the pool is empty and convertView will be null
if(convertView == null)
{
//If convertView is null, inflate it, something like this....
convertView = layoutInflator.inflate(R.layout.mylistview, null);
}
//If convertView was not null, it has previously been inflated by this method
//Now, you can use the position argument to find this view's data and populate it
//It is important in this step to reset the entire state of the view.
//If the view that was popped off the list had a checked CheckBox,
// it will still be selected, EditTexts will not be cleared, etc.
//Finally, once that configuration is done, return convertView
return convertView;
}
Adapter类中还有许多其他方法可以帮助您管理列表,并允许您执行利用视图回收的聪明工具,例如getItem()
用于管理基础数据,以及getViewType()
和getViewTypeCount()
用于包含多种视图类型的列表,但上述内容是基本技术,也是视图平滑运行所需的最小技术。
听起来你走在正确的轨道上,我希望这有助于回答你的一些问题。如果您不了解更多信息,请告诉我。
答案 1 :(得分:1)
你正在以正确的方式做到这一点。在Android中,您应该跟踪每个列表项的状态。调用getView
时,您可以选择重复使用或为该行创建新视图。通过跟踪项目的状态(文本,选中,背景等),您可以轻松地重置已存在的视图。 跟踪详细状态将帮助您确保没有其他行受到一行更改的影响
当您致电adapter.notifyDataSetChanged()
时,重绘的唯一项目是屏幕上的项目(或非常靠近屏幕)。