ListView性能
使用基於ListView的應用程序確保卓越的性能。
- PDF用於離線使用
- 相關樣品:
- 相關API:
讓我們知道你對此的感受
最後更新:2016年12月
在編寫移動應用時,性能很重要。用戶預期平滑滾動和快速加載時間。如果不能滿足用戶的期望,您的應用商店中的評分將會降低,或者在業務線應用程序的情況下,會使您的組織花費時間和金錢。
雖然ListView
是顯示數據的強大視圖,但它有其侷限性。使用自定義單元格時,滾動性能會受到影響,特別是當它們包含深層次的視圖層次結構或使用需要大量測量的某些佈局時。幸運的是,有一些技術可以用來避免性能不佳。
本文將討論以下主題:
緩存策略
ListViews通常用於顯示比可以適合屏幕的數據更多的數據。考慮一個音樂應用程序,例如。歌曲庫可能有成千上萬的條目。一個簡單的方法,即爲每一首歌曲創建一行,將表現不佳。這種方法浪費寶貴的內存,並可以緩慢滾動到爬網。另一種方法是在數據滾動到視圖中時創建和銷燬行。這需要對視圖對象進行不間斷的實例化和清理,這可能非常慢。
爲了節省內存,ListView
每個平臺的本機等價物具有內置的重新使用行的功能。只有屏幕上可見的單元格才能加載到內存中,並將內容加載到現有的單元格中。這樣可以防止應用程序實例化數千個對象,節省時間和內存。
Xamarin.Forms 2 ListView
通過ListViewCachingStrategy
枚舉引入單元格重用,它具有以下值:
public enum ListViewCachingStrategy
{
RetainElement // the default value
RecycleElement
}
RetainElement
該RetainElement
值指定ListView
將爲列表中的每個項生成一個單元格。這是ListView
Xamarin.Forms
2之前的行爲,是默認ListView
行爲。一般應在以下情況下使用:
- 當每個單元格具有大量綁定(20-30 +)時。
- 當單元格模板頻繁更改時。
- 當測試顯示該
RecycleElement
值導致執行速度降低。
RetainElement
在使用自定義單元格時,必須認識到該值的後果。任何單元初始化代碼都需要爲每個單元格創建運行,這可能是每秒多次。在這種情況下,頁面上的佈局技術(如使用多個嵌套StackLayout
實例)在用戶滾動時被實時設置和銷燬時成爲性能瓶頸。
RecycleElement
該RecycleElement
值指定ListView
將通過循環列表單元來嘗試最小化其內存佔用空間和執行速度。該模式並不總是提供性能改進,並且應該執行測試以確定任何改進。但是,通常是首選,應在以下情況下使用:
- 當每個單元格具有小到中等數量的綁定。
- 當每個單元格
BindingContext
定義所有單元格數據時。 - 當每個單元格大體相似時,單元格模板不變。
在虛擬化期間,單元格將更新其綁定上下文,因此如果應用程序使用此模式,則必須確保正確處理綁定上下文更新。關於單元格的所有數據必須來自綁定上下文或可能發生一致性錯誤。這可以通過使用數據綁定來顯示單元格數據來實現。或者,單元格數據應該在OnBindingContextChanged
覆蓋中設置,而不是在自定義單元格的構造函數中設置,如下面的代碼示例所示:
public class CustomCell : ViewCell
{
Image image = null;
public CustomCell ()
{
image = new Image();
View = image;
}
protected override void OnBindingContextChanged ()
{
base.OnBindingContextChanged ();
var item = BindingContext as ImageItem;
if (item != null) {
image.Source = item.ImageUrl;
}
}
}
有關更多信息,請參閱綁定上下文更改。
在iOS和Android上,如果單元格使用自定義渲染器,則必須確保正確實施屬性更改通知。當重新使用單元格時,當綁定上下文更新爲可用單元格的屬性值時,其屬性值將更改,並PropertyChanged
引發事件。有關詳細信息,請參閱自定義ViewCell。
設置緩存策略
該ListViewCachingStrategy
值由ListView
構造函數重載指定,如以下代碼示例所示:
var listView = new ListView(ListViewCachingStrategy.RecycleElement);
在XAML中,CachingStrategy
按如下代碼設置屬性:
<ListView CachingStrategy="RecycleElement">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
...
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
這與在C#中的構造函數中設置緩存策略參數具有相同的效果。注意沒有CachingStrategy
財產ListView
。
在Subclassed ListView中設置緩存策略
在CachingStrategy
XAML子類上設置屬性ListView
不會產生所需的行爲,因爲沒有CachingStrategy
屬性ListView
。另外,如果啓用了XAMLC,將會產生以下錯誤消息:沒有爲'CachingStrategy'找到屬性,可綁定屬性或事件
解決這個問題的方法是在子類上指定一個ListView
接受ListViewCachingStrategy
參數並將其傳遞給基類的構造函數:
public class CustomListView : ListView
{
public CustomListView (ListViewCachingStrategy strategy) : base (strategy)
{
}
...
}
然後ListViewCachingStrategy
可以使用以下x:Arguments
語法從XAML指定該值:
<local:CustomListView>
<x:Arguments>
<ListViewCachingStrategy>RecycleElement</ListViewCachingStrategy>
</x:Arguments>
</local:CustomListView>
提高ListView性能
有很多技術來提高性能ListView
:
- 將
ItemsSource
屬性綁定到IList<T>
集合而不是IEnumerable<T>
集合,因爲IEnumerable<T>
集合不支持隨機訪問。 - 使用內置單元格(如
TextCell
/SwitchCell
),而不是ViewCell
隨時可用。 - 使用較少的元素。例如考慮使用單個
FormattedString
標籤而不是多個標籤。 - 當顯示非均勻數據時,替換爲
ListView
aTableView
,即不同類型的數據。 - 限制使用該
Cell.ForceUpdateSize
方法。如果過度使用,會降低性能。 - 在Android上,避免
ListView
在實例化之後設置行分隔符的可見性或顏色,因爲會導致性能下降。 - 避免改變單元佈局
BindingContext
。這導致了很大的佈局和初始化成本。 - 避免深層嵌套的佈局層次結構。使用
AbsoluteLayout
或Grid
幫助減少嵌套。 - 避免特定
LayoutOptions
比其他Fill
(填充是最便宜的計算)。 - 避免放置
ListView
內部ScrollView
,原因如下:- 在
ListView
實現了自己的滾動。 - 該
ListView
不會收到任何手勢,因爲他們會被家長進行處理ScrollView
。 - 所述
ListView
可呈現定製的頁眉和頁腳,與列表的元素滾動,潛在地提供該功能ScrollView
用於。有關更多信息,請參閱頁眉和頁腳。
- 在
- 如果您需要在單元格中提供的非常具體,複雜的設計,請考慮自定義渲染器。
AbsoluteLayout
有可能執行佈局,而無需單次測量。這使它非常強大的性能。如果AbsoluteLayout
不能使用,請考慮RelativeLayout
。如果使用RelativeLayout
,直接傳遞約束將比使用表達式API快得多。這是因爲表達式API使用JIT,而在iOS上,必須解釋樹,這是較慢的。表達式API適用於僅在初始佈局和旋轉時需要的頁面佈局,但是在ListView
滾動時不斷運行的頁面佈局會降低性能。
ListView
爲其單元格構建自定義渲染器是減少佈局計算對滾動性能的影響的一種方法。有關更多信息,請參閱自定義ListView並自定義ViewCell。