2011-05-12 76 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

相關問題