我今天學習了Android的ArrayAdapter,發現有一個通用模式,它使用ViewHolder來保存Views的引用,而不是每次調用findViewById。爲什麼ViewHolder模式有效?
但它是如何工作的?適配器通常用於顯示視圖(組)的列表,如果我緩存視圖,爲什麼他們都不參考最老的?
我今天學習了Android的ArrayAdapter,發現有一個通用模式,它使用ViewHolder來保存Views的引用,而不是每次調用findViewById。爲什麼ViewHolder模式有效?
但它是如何工作的?適配器通常用於顯示視圖(組)的列表,如果我緩存視圖,爲什麼他們都不參考最老的?
如果您想了解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將使它比我能寫的任何東西更清晰。
我相信列表視圖下的工作是這樣的(考慮到我們只有一個項目視圖類型):
做一次:對於每一個項目
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查找來加快速度。
這樣只有一個視圖,它如何將數據填充到不同的位置(例如TextView)? – 2011-05-12 08:13:59
@Lai Yu-Hsuan它需要第一個項目,將所有數據從適配器填充到textFields等等,繪製這個視圖,移動到下一個項目,重複..你不必爲每個項目都有單獨的視圖對象那 – 2011-05-12 09:12:14
哦,我明白了。所以我們重複使用這個視圖:一個例子,多次繪製,righr?所以我想我不能在視圖層次結構中訪問這些視圖? – 2011-05-12 09:43:21
對不起,但denis的答案可能是錯的。 實際上,視圖實例(和ViewHolders)爲,與您的屏幕可顯示一樣多。
如果你的屏幕看起來像:
[list view]
the first item
the second item
the third item
the fourth item
你有意見4個實例。如果您滾動屏幕,則第一項將消失,但會傳遞給getItem()作爲convertView
供您創建第五項。
因此,您可以使用第一個ViewHolder中的引用。
這意味着在繪製第一個項目ListView時創建視圖,而不是將其作爲「convertView」傳遞。如果你從'getItem'返回相同的'convertView',那麼你在渲染第二個項目時又會看到相同的視圖.. :)不會有兩個視圖,對吧? – 2011-05-13 05:31:16
我認爲這是......錯的。至少accroding我在#android-dev上聽到的。只有在視圖消失後才能重用視圖。因此,如果您的屏幕大於一個項目,則無法使用第一個視圖來繪製第二個項目。如果屏幕上有N個項目,則有N個視圖實例。 – 2011-05-13 05:45:59
查看源代碼後,我必須同意該算法不像我想象的那麼簡單和直接。它涉及一些意見,其中一些是可重用的,有些則不是。將不得不挖掘更多的來源,以瞭解發生了什麼.. – 2011-05-13 06:03:02
感謝指出這樣一個信息豐富和真棒視頻。 – 2011-06-24 20:07:59