1

我已经多次遇到这个问题,通过快速搜索很容易找到许多类似的问题。有时 ListView 行布局上的动态更改也会影响其他行,有时则不会。

作为这个问题的解决方案,我通常会跟踪列表中的整个项目集,每次我有更改时,我都会重置列表中的所有项目。

例如:如果我有一个带有 TextViews 和复选框的列表,我必须保留一个布尔数组,指示每个复选框的状态,并在我的 getView() 覆盖上重置基于该数组的所有复选框。

这是预期的吗?我可以找到有关此问题的几个问题,并且所有解决方案似乎都与我的相似。

现在我面临一个问题,我需要在一个非常长的列表中一次跟踪多个项目(背景、复选框和文本)。我想知道这个问题是否有其他方法。

4

2 回答 2

2

这是 Android 中 ListViews 的预期行为。您使用基础数据填充列表中的视图的方法是正确的。

在创建 ListView 时,Android 使用了一种称为 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()多种视图类型的列表,但以上是基本的技术和您的视图顺利运行所需的最低要求。

听起来你走在正确的轨道上,我希望这有助于回答你的一些问题。如果有任何不清楚的地方,请告诉我您需要更多信息。

于 2013-03-14T14:08:13.337 回答
1

你做对了。在 Android 中,您应该跟踪每个单独列表项的状态。当getView被调用时,您可以选择重用或为该行创建新视图。通过跟踪项目的状态(文本、已检查、背景等),您可以轻松地重置已经存在的视图。跟踪详细状态将帮助您确保没有其他行受到一行更改的影响

当您调用时adapter.notifyDataSetChanged(),唯一重绘的项目是屏幕上的项目(或非常接近屏幕上的项目)。

于 2013-03-14T13:43:31.450 回答