ArrayAdapter的getViewTypeCount和getItemViewType方法


159

有人可以用简单的语言解释我的用法getViewTypeCount()getItemViewType()方法ArrayAdapter吗?

Answers:


308

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

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

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

该框架使用您的视图类型来决定在您的方法中要通过哪些视图convertViewgetView。换句话说,在上面的示例中,您的偶数行将仅获得左侧带有图片的可回收视图以供重用,而奇数行将仅获得右侧带有图片的视图。

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

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

public int getViewTypeCount() {
    return 1;
}

实际上,这为您提供了每行相同的视图类型。

编辑 -概述总体流程:

  1. AdapterView使用适配器将数据绑定到您。
  2. AdapterView尝试显示是对用户可见的项目。
  3. 框架要求getItemViewTyperow n,它将要显示的行。
  4. 框架检查其回收的视图池中是否有row n类型的视图。它找不到任何内容,因为尚未回收任何视图。
  5. getView被要求排n
  6. 您要求getItemViewTypen确定应该使用哪种视图类型。
  7. 您使用if / switch语句根据所需的视图类型为另一个xml文件充气。
  8. 您用信息填充视图。
  9. 您返回视图,退出getView,并且行的视图将显示给用户。

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

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

1
@Matthew,谢谢您的回答。您能描述一下如何调用这些方法的流程。另外我不明白这实际上是如何与res / layout中的数据关联的。
尤金(Eugene)

这些方法何时被调用没有明确的约定。res / layout是查看对象的地方。这是一个适配器。您应该在getView方法中检查项目类型,并相应地从res / layout填充正确的视图。
马修·威利斯,

1
您将自己在getItemViewType中返回它。
马修·威利斯,

您可以在getView中手动进行关联:if(type == 0){/ *扩展R.layout.row_icon_on_left /} else {/扩展R.layout.row_icon_on_right * /}
Matthew Willis

75
谨防!1. - getItemViewType()必须在0和getViewTypeCount()之间返回int
PacificSky

12

如果我们需要在列表视图中显示不同类型的视图,则它很好用getViewTypeCount()getItemViewType()在适配器中使用,而不是切换视图,View.GONE并且这View.VISIBLE可能是非常昂贵的任务,getView()这会影响列表滚动。

请检查这一项要求使用的getViewTypeCount()getItemViewType()适配器。

链接:getview的使用类型计数


在getItemViewType()中返回IGNORE_ITEM_VIEW_TYPE将始终在getView(int position,View view,ViewGroup viewGroup)中将'view'作为null传递,强制初始化所有UI组件。这不是一个糟糕的性能指标,在这种情况下,如果使用持有人模式,我们将重用现有的UI视图,并且可以根据位置将视图切换为View.GONE或View.VISIBLE。
Namrata Bagerwal

11

看Outttt !!!!
我不得不面对实现ListView昨天的问题,滚动它后,有两种类型的行视图变得混乱。即使该线程中投票最高的答案给出了很好的一般解释,它也没有突出显示最重要的信息来阻止我提到的UI错误。

这是我的解释是:
这两个getViewTypeCount()getItemViewType()正在使用BaseAdaptergetView方法来找出哪些类型的视图它应该被取,回收并返回。(如该线程顶部回答中所述)。但是,如果您没有按照Android API文档直观地实现这两种方法,那么您可能会遇到我提到的问题。

实施指南概述:
要实现多种类型的Viewsfor ListView行,我们必须实质上实现getItemViewType()getViewTypeCount()方法。和getItemViewType()文档给了我们一个提示如下:

注:整数必须在范围0getViewTypeCount() - 1IGNORE_ITEM_VIEW_TYPE也可以退货。

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

无论如何,如果您为此方法返回任何其他整数值(例如1、2、3或111、222、333),则肯定会遇到上述UI错误,因为您不遵守Android API文档而被放置。

如果您没有找到线索或仍然无法解决,并且需要更多信息,请阅读我在StackOverflow问答环节中的详细答案

阅读Android开发者文档以获取更多信息,您可能直接找到线索。

希望此答案对那里的人可以节省很多时间!

干杯!!!


1
感谢您提到IGNORE_ITEM_VIEW_TYPE我的一个ListView上有一个错误。我使用ArrayAdapter插入由1个图像和2个文本视图组成的视图。我只有一种视图类型。我试图要么不重写getItemViewType方法,要么通过返回位置或硬编码整数来重写它。在所有情况下,我的列表中都有重复项,滚动时行为很奇怪(重复项更改)。返回IGNORE_ITEM_VIEW_TYPE方法解决了该问题。谢谢。
亚历克斯

@Alex很高兴这对您有所帮助!:-)
Randika Vishman'8
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.