2011-05-12 77 views
2

我今天学习了Android的ArrayAdapter,发现有一个通用模式,它使用ViewHolder来保存Views的引用,而不是每次调用findViewById。为什么ViewHolder模式有效?

但它是如何工作的?适配器通常用于显示视图(组)的列表,如果我缓存视图,为什么他们都不参考最老的?

回答

13

如果您想了解ViewHolder工作原理的最佳解释,请在youtube(特别是前15分钟)中查看Romain Guy的Google I/O 2009对话。

简而言之,Adapter用作底层数据和ViewGroup之间的链接。它将根据需要渲染尽可能多的填充屏幕。在滚动或其他任何推动View不在屏幕上的事件时,Adapter将重新使用填充了正确数据的View以在屏幕上呈现。

getView(int pos, View view, ViewGroup parent)方法将随时使用正确的View,无论您的布局如何。我不知道这个内部,但我确定你可以浏览任何适配器的源代码(如ArrayAdapter.java),如果你有兴趣。
ViewHolder只是保持指向Views的指针,由view.findViewById(int id)获得。适配器的责任是返回与任何位置相对应的正确数据。

幻灯片11到13的Romain's presentation将使它比我能写的任何东西更清晰。

+0

感谢指出这样一个信息丰富和真棒视频。 – 2011-06-24 20:07:59

0

我相信列表视图下的工作是这样的(考虑到我们只有一个项目视图类型):

做一次:对于每一个项目

inflate item view from layout, cache it 

重复:

ask adapter to fill the data into the view 
draw the view on the screen 
move to next item 

所以你有从xml布局夸大的视图,可以重复使用绘制多个列表项。 ViewHolder通过保存getViewById查找来加快速度。

+0

这样只有一个视图,它如何将数据填充到不同的位置(例如TextView)? – 2011-05-12 08:13:59

+0

@Lai Yu-Hsuan它需要第一个项目,将所有数据从适配器填充到textFields等等,绘制这个视图,移动到下一个项目,重复..你不必为每个项目都有单独的视图对象那 – 2011-05-12 09:12:14

+0

哦,我明白了。所以我们重复使用这个视图:一个例子,多次绘制,righr?所以我想我不能在视图层次结构中访问这些视图? – 2011-05-12 09:43:21

1

对不起,但denis的答案可能是错的。 实际上,视图实例(和ViewHolders)为,与您的屏幕可显示一样多。

如果你的屏幕看起来像:

[list view] 
the first item 
the second item 
the third item 
the fourth item 

你有意见4个实例。如果您滚动屏幕,则第一项将消失,但会传递给getItem()作为convertView供您创建第五项。

因此,您可以使用第一个ViewHolder中的引用。

+0

这意味着在绘制第一个项目ListView时创建视图,而不是将其作为“convertView”传递。如果你从'getItem'返回相同的'convertView',那么你在渲染第二个项目时又会看到相同的视图.. :)不会有两个视图,对吧? – 2011-05-13 05:31:16

+0

我认为这是......错的。至少accroding我在#android-dev上听到的。只有在视图消失后才能重用视图。因此,如果您的屏幕大于一个项目,则无法使用第一个视图来绘制第二个项目。如果屏幕上有N个项目,则有N个视图实例。 – 2011-05-13 05:45:59

+0

查看源代码后,我必须同意该算法不像我想象的那么简单和直接。它涉及一些意见,其中一些是可重用的,有些则不是。将不得不挖掘更多的来源,以了解发生了什么.. – 2011-05-13 06:03:02

相关问题