Výkon ListView
Při psaní mobilních aplikací záleží na výkonu. Uživatelé přišli očekávat hladké posouvání a rychlé načítání. Když se vám nepodaří splnit očekávání vašich uživatelů, budou vám náklady na hodnocení v obchodě s aplikacemi nebo v případě obchodní aplikace stát čas a peníze vaší organizace.
Jedná se Xamarin.FormsListView
o výkonné zobrazení pro zobrazení dat, ale má určitá omezení. Při používání vlastních buněk může dojít k snížení výkonu posouvání, zejména pokud obsahují hluboko vnořené hierarchie zobrazení nebo používají určitá rozložení, která vyžadují komplexní měření. Naštěstí existují techniky, které můžete použít, abyste se vyhnuli nízkému výkonu.
Strategie ukládání do mezipaměti
Objekty ListView se často používají k zobrazení mnohem více dat, než se vejde na obrazovku. Hudební aplikace může mít například knihovnu skladeb s tisíci položek. Vytvoření položky pro každou položku by ztrácelo cennou paměť a fungovalo špatně. Vytváření a zničení řádků by neustále vyžadovalo vytvoření instance a vyčištění objektů aplikace, což by také fungovalo špatně.
Pro zachování paměti mají nativní ListView
ekvivalenty pro každou platformu integrované funkce pro opakované využití řádků. Do paměti se načtou jenom buňky viditelné na obrazovce a obsah se načte do existujících buněk. Tento model brání aplikaci v vytváření instancí tisíců objektů, což šetří čas a paměť.
Xamarin.FormsListView
umožňuje opakované použití buněk prostřednictvím výčtuListViewCachingStrategy
, který má následující hodnoty:
public enum ListViewCachingStrategy
{
RetainElement, // the default value
RecycleElement,
RecycleElementAndDataTemplate
}
Poznámka:
Univerzální platforma Windows (UPW) ignoruje RetainElement
strategii ukládání do mezipaměti, protože ke zlepšení výkonu vždy používá ukládání do mezipaměti. Ve výchozím nastavení se proto chová jako při RecycleElement
použití strategie ukládání do mezipaměti.
ZachovatElement
Strategie RetainElement
ukládání do mezipaměti určuje, že ListView
se pro každou položku v seznamu vygeneruje buňka a že se jedná o výchozí ListView
chování. Měla by být použita za následujících okolností:
- Každá buňka má velký počet vazeb (20-30+).
- Šablona buňky se často mění.
- Testování ukazuje, že
RecycleElement
strategie ukládání do mezipaměti vede ke snížení rychlosti provádění.
Při práci s vlastními buňkami je důležité rozpoznat důsledky RetainElement
strategie ukládání do mezipaměti. Každý inicializační kód buňky bude potřeba spustit pro každé vytvoření buňky, což může být několikrát za sekundu. V této situaci se techniky rozložení, které byly na stránce v pořádku, jako je použití více vnořených StackLayout
instancí, stanou kritickými body výkonu při jejich nastavení a zničení v reálném čase při posouvání uživatele.
RecycleElement
Strategie RecycleElement
ukládání do mezipaměti určuje, že ListView
se pokusí minimalizovat nároky na paměť a rychlost spouštění díky recyklaci buněk seznamu. Tento režim nenabízí vždy zlepšení výkonu a testování by se mělo provést, aby bylo možné určit všechna vylepšení. Je to ale upřednostňovaná volba a měla by se použít za následujících okolností:
- Každá buňka má malý až střední počet vazeb.
- Každá buňka
BindingContext
definuje všechna data buněk. - Každá buňka je z velké části podobná a šablona buňky se nemění.
Během virtualizace bude mít buňka aktualizovaný kontext vazby, takže pokud aplikace používá tento režim, musí zajistit, aby aktualizace kontextu vazby byly zpracovány odpovídajícím způsobem. Všechna data o buňce musí pocházet z kontextu vazby nebo mohou nastat chyby konzistence. Tento problém lze vyhnout pomocí datové vazby k zobrazení dat buňky. Další možností je nastavit data buňky v OnBindingContextChanged
přepsání, nikoli v konstruktoru vlastní buňky, jak je znázorněno v následujícím příkladu kódu:
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;
}
}
}
Další informace naleznete v tématu Změny kontextu vazby.
Pokud buňky v iOSu a Androidu používají vlastní renderery, musí zajistit správnou implementaci oznámení o změně vlastnosti. Při opakovaném použití buněk se hodnoty vlastností změní při aktualizaci kontextu vazby na dostupnou buňku s PropertyChanged
vyvoláním událostí. Další informace naleznete v tématu Přizpůsobení ViewCell.
RecycleElement s objektem DataTemplateSelector
ListView
Pokud se použije DataTemplateSelector
k výběru , DataTemplate
RecycleElement
strategie ukládání do mezipaměti neukládá mezipamětiDataTemplate
. DataTemplate
Místo toho je vybrána pro každou položku dat v seznamu.
Poznámka:
Strategie RecycleElement
ukládání do mezipaměti má předpoklad zavedený ve Xamarin.Forms verzi 2.4, že když DataTemplateSelector
se zobrazí výzva k výběru DataTemplate
, který musí každý DataTemplate
vrátit stejný ViewCell
typ. Pokud je například vrácena ListView
hodnota typu DataTemplateSelector
, která může vrátit buď MyDataTemplateA
(kde MyDataTemplateA
vrátí ViewCell
typ MyViewCellA
), nebo MyDataTemplateB
(kde MyDataTemplateB
vrátí ViewCell
typ MyViewCellB
), když MyDataTemplateA
je vrácena, musí vrátit MyViewCellA
nebo se vyvolá výjimka.
RecycleElementAndDataTemplate
Strategie RecycleElementAndDataTemplate
ukládání do mezipaměti je založená na RecycleElement
strategii ukládání do mezipaměti tím, že navíc zajišťuje, že když ListView
se použije DataTemplateSelector
k výběru , DataTemplate
DataTemplate
budou uloženy v mezipaměti podle typu položky v seznamu. DataTemplate
Proto jsou vybrány jednou za typ položky místo jednou na instanci položky.
Poznámka:
RecycleElementAndDataTemplate
Strategie ukládání do mezipaměti má předpoklad, že DataTemplate
vrácené vrácené DataTemplateSelector
musí použít DataTemplate
konstruktor, který přebírá Type
.
Nastavení strategie ukládání do mezipaměti
Hodnota ListViewCachingStrategy
výčtu je zadána s přetížením konstruktoru ListView
, jak je znázorněno v následujícím příkladu kódu:
var listView = new ListView(ListViewCachingStrategy.RecycleElement);
V JAZYCE XAML nastavte CachingStrategy
atribut, jak je znázorněno v následujícím kódu XAML:
<ListView CachingStrategy="RecycleElement">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
...
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Tato metoda má stejný účinek jako nastavení argumentu strategie ukládání do mezipaměti v konstruktoru v jazyce C#.
Nastavení strategie ukládání do mezipaměti v podtřídě ListView
Nastavení atributu CachingStrategy
z XAML v podtřídě ListView
nevyvolá požadované chování, protože neexistuje žádná CachingStrategy
vlastnost ListView
. Kromě toho, pokud je povolen XAMLC , bude vytvořena následující chybová zpráva: Žádná vlastnost, bindable vlastnost nebo událost nalezena pro 'CachingStrategy'
Řešením tohoto problému je zadat konstruktor v podtřídě ListView
, který přijímá ListViewCachingStrategy
parametr a předává ho do základní třídy:
public class CustomListView : ListView
{
public CustomListView (ListViewCachingStrategy strategy) : base (strategy)
{
}
...
}
Potom lze hodnotu výčtu ListViewCachingStrategy
zadat z XAML pomocí x:Arguments
syntaxe:
<local:CustomListView>
<x:Arguments>
<ListViewCachingStrategy>RecycleElement</ListViewCachingStrategy>
</x:Arguments>
</local:CustomListView>
Návrhy výkonu ListView
Existuje mnoho technik pro zlepšení výkonu ListView
. Následující návrhy můžou zlepšit výkon zobrazení ListView.
ItemsSource
Vytvořte vazbu vlastnosti naIList<T>
kolekci místoIEnumerable<T>
kolekce, protožeIEnumerable<T>
kolekce nepodporují náhodný přístup.- Místo toho používejte předdefinované buňky (například
TextCell
/SwitchCell
) místoViewCell
toho, abyste je mohli použít. - Používejte méně prvků. Zvažte například použití jednoho
FormattedString
popisku místo více popisků. ListView
Nahraďte hoTableView
při zobrazení nehomogenních dat – to znamená dat různých typů.- Omezte použití
Cell.ForceUpdateSize
metody. Pokud dojde k nadměrnému výkonu, sníží se výkon. - V Androidu se vyhněte nastavení
ListView
viditelnosti nebo barvy oddělovače řádků po vytvoření instance, protože výsledkem je velký výkon. - Vyhněte se změně rozložení buňky na základě .
BindingContext
Změna rozložení způsobuje velké náklady na měření a inicializaci. - Vyhněte se hluboko vnořeným hierarchií rozložením. Použijte
AbsoluteLayout
neboGrid
pomozte snížit vnoření. - Vyhněte se jiným než
LayoutOptions
Fill
(Fill
je nejlevnější pro výpočty). - Vyhněte se umístění
ListView
uvnitř zScrollView
následujících důvodů:- Implementuje
ListView
vlastní posouvání. - Nebudou
ListView
přijímat žádná gesta, protože bude zpracována nadřazenýmScrollView
objektem . - Může
ListView
prezentovat přizpůsobené záhlaví a zápatí, které se posune s prvky seznamu, a potenciálně nabízí funkce, pro kteréScrollView
byl použit. Další informace najdete v tématu Záhlaví a zápatí.
- Implementuje
- Pokud potřebujete konkrétní komplexní návrh zobrazený v buňkách, zvažte vlastní renderer.
AbsoluteLayout
má potenciál provádět rozložení bez jediného volání míry, což z něj dělá vysoce výkonné. Pokud AbsoluteLayout
nelze použít, zvažte RelativeLayout
. Pokud používáte RelativeLayout
, předávání omezení přímo bude výrazně rychlejší než použití rozhraní API pro výrazy. Tato metoda je rychlejší, protože rozhraní API výrazů používá JIT a v iOSu je potřeba strom interpretovat, což je pomalejší. Rozhraní API výrazu je vhodné pro rozložení stránek, kde se vyžaduje pouze při počátečním rozložení a otočení, ale v místě, kde ListView
se při posouvání spouští neustále, snižuje výkon.
Vytvoření vlastního rendereru ListView
pro buňky nebo jeho buněk je jedním z přístupů ke snížení vlivu výpočtů rozložení při posouvání výkonu. Další informace naleznete v tématu Přizpůsobení objektu ListView a přizpůsobení objektu ViewCell.