【问题标题】:getViewTypeCount and getItemViewType methods of ArrayAdapterArrayAdapter 的 getViewTypeCount 和 getItemViewType 方法
【发布时间】:2011-03-14 15:47:29
【问题描述】:

有人可以简单地解释一下ArrayAdaptergetViewTypeCount()getItemViewType() 方法的用法吗?

【问题讨论】:

    标签: android


    【解决方案1】:

    这些处理您希望不同行的不同类型视图的情况。例如,在联系人应用程序中,您可能希望偶数行在左侧有图片,而奇数行在右侧有图片。在这种情况下,您将使用:

    @Override
    public int getViewTypeCount() {
        return 2;
    }
    
    @Override
    public int getItemViewType(int position) {
        return position % 2;
    }
    

    框架使用您的视图类型来决定在您的getView 方法中通过convertView 将哪些视图交给您。换句话说,在上面的例子中,你的偶数行只会得到左侧有图片的循环视图以重复使用,而奇数行只会得到右侧有图片的视图。

    如果列表中的每一行都具有相同的布局,则无需担心视图类型。事实上,BaseAdapter.java 为所有适配器提供了默认行为:

    public int getItemViewType(int position) {
        return 0;
    }
    
    public int getViewTypeCount() {
        return 1;
    }
    

    这确实为每一行提供了相同的视图类型。

    编辑 - 概述一般流程:

    1. 您使用适配器将数据绑定到您的AdapterView
    2. AdapterView 尝试显示用户可见的项目。
    3. 框架调用getItemViewType 获取行n,即将显示的行。
    4. 框架检查其回收的视图池中的行n 类型的视图。它没有找到任何视图,因为尚未回收任何视图。
    5. getView 被称为行 n
    6. 您为行 n 调用 getItemViewType 以确定您应该使用哪种类型的视图。
    7. 您可以使用 if/switch 语句来扩展不同的 xml 文件,具体取决于所需的视图类型。
    8. 您用信息填充视图。
    9. 您返回视图,退出getView,您所在行的视图将显示给用户。

    现在,当通过滚动屏幕来回收视图时,它会进入由框架管理的回收视图池。这些基本上是按视图类型组织的,以便在您的 getView 方法中的 convertView 参数中为您提供正确类型的视图:

    1. 框架再次为要显示的行调用getItemViewType
    2. 这一次,在适当类型的回收池中有一个视图。
    3. 回收的视图作为convertView 参数传递给您的getView 方法。
    4. 您用新信息填充循环视图并将其返回。

    【讨论】:

    • @Matthew,感谢您的回答。你能描述一下如何调用这些方法的流程吗?我也不明白这实际上是如何与我在 res/layout 中的数据相关联的。
    • 没有明确的约定何时调用这些方法。 res/layout 是 view 对象的地方。这是一个适配器。您应该在 getView 方法中检查项目类型,并相应地从 res/layout 中扩展正确的视图。
    • 您自己在 getItemViewType 中返回它。
    • 您在 getView 中手动进行关联: if (type == 0) { /* inflate R.layout.row_icon_on_left / } else { / inflate R.layout.row_icon_on_right */ }
    • 当心! getItemViewType() 必须返回一个介于 0 和 getViewTypeCount() - 1 之间的 int。
    【解决方案2】:

    如果我们需要在列表视图中显示不同类型的视图,那么最好在适配器中使用 getViewTypeCount()getItemViewType() 而不是切换视图 View.GONEView.VISIBLE 在 @987654326 中可能是非常昂贵的任务@ 会影响列表滚动。

    请检查这一项是否在适配器中使用getViewTypeCount()getItemViewType()

    链接:the-use-of-getviewtypecount

    【讨论】:

    • 在 getItemViewType() 中返回 IGNORE_ITEM_VIEW_TYPE 将始终在 getView(int position, View view, ViewGroup viewGroup) 中将“view”作为 null 传递,从而强制初始化所有 UI 组件。这不是一个糟糕的性能指标,在持有者模式的情况下,我们可以重用现有的 UI 视图,我们可以简单地根据位置将视图切换到 View.GONE 或 View.VISIBLE。
    【解决方案3】:

    注意!!!!
    昨天我不得不面对实现ListView 的问题,并且在我滚动它之后,两种类型的行视图变得混乱。尽管该线程中投票最多的答案给出了一个很好的一般解释,但它并没有突出显示最重要的信息来阻止我提到的上述 UI 错误。

    这是我的解释:
    getViewTypeCount()getItemViewType() 都被BaseAdaptergetView 方法用来找出应该获取、回收和返回哪种类型的视图。 (如线程中的最佳答案中所述)。但是如果你不按照Android API Doc直观地实现这两个方法,那么你可能会遇到我提到的问题。

    实施指南摘要:
    要为ListView 的行实现多种类型的Views,我们必须基本上实现getItemViewType()getViewTypeCount() 方法。而getItemViewType() 文档给了我们如下注释:

    注意:整数必须在0getViewTypeCount() - 1 的范围内。 IGNORE_ITEM_VIEW_TYPE也可以返回。

    因此,在您的getItemViewType() 中,您应该返回视图类型的值,从 0 开始,到最后一个类型(类型数 - 1)。例如,假设您只有三种视图?因此,根据视图的数据对象,您只能从 getItemViewType() 方法返回 012,如零- 基于数组索引。由于您使用了三种类型的视图, 您的 getViewTypeCount() 方法必须返回 3。

    在任何情况下,如果您为此方法返回任何其他整数值,例如 1、2、3 或 111、222、333,您肯定可能会遇到上述 UI 错误,因为您不遵守 Android API 文档。

    如果您没有得到线索或仍然无法解决并需要更多信息,请阅读我的detailed answer within this StackOverflow Q&A thread

    阅读Android Developer Doc 了解更多信息,您可能会直接找到线索。

    希望这个答案可能对那里的人有所帮助,以节省大量时间!!!

    干杯!!!

    【讨论】:

    • 感谢您提及IGNORE_ITEM_VIEW_TYPE 我的一个 ListView 有一个错误。我使用 ArrayAdapter 插入由 1 个图像和 2 个文本视图组成的视图。我只有一种视图类型。我尝试不覆盖方法 getItemViewType,或者通过返回位置或硬编码整数来覆盖它。在所有情况下,我都在列表中遇到重复,滚动时出现奇怪的行为(重复更改)。在方法中返回 IGNORE_ITEM_VIEW_TYPE 解决了这个问题。谢谢。
    • @Alex 很高兴它对您有所帮助! :-)
    猜你喜欢
    • 1970-01-01
    • 2012-05-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-06
    • 1970-01-01
    相关资源
    最近更新 更多