Prestazioni di ListView
Quando si scrivono applicazioni per dispositivi mobili, le prestazioni sono importanti. Gli utenti si aspettano tempi di scorrimento e caricamento rapidi. Se non si soddisfano le aspettative degli utenti, si costeranno valutazioni nell'archivio applicazioni o nel caso di un'applicazione line-of-business, costare tempo e denaro per l'organizzazione.
è Xamarin.FormsListView
una visualizzazione potente per la visualizzazione dei dati, ma presenta alcune limitazioni. Le prestazioni di scorrimento possono risentire quando si usano celle personalizzate, soprattutto quando contengono gerarchie di visualizzazione annidate in profondità o si usano determinati layout che richiedono una misurazione complessa. Fortunatamente, esistono tecniche che è possibile usare per evitare prestazioni scarse.
Strategia di memorizzazione nella cache
Le visualizzazioni ListView vengono spesso usate per visualizzare molti più dati rispetto a quelli visualizzati sullo schermo. Ad esempio, un'app musicale potrebbe avere una libreria di canzoni con migliaia di voci. La creazione di un elemento per ogni voce potrebbe sprecare memoria preziosa e prestazioni scarse. La creazione e l'eliminazione costante di righe richiederebbero all'applicazione di creare istanza e pulire gli oggetti in modo costante, con prestazioni anche scarse.
Per risparmiare memoria, gli equivalenti nativi ListView
per ogni piattaforma hanno funzionalità predefinite per il riutilizzo delle righe. Solo le celle visibili sullo schermo vengono caricate in memoria e il contenuto viene caricato nelle celle esistenti. Questo modello impedisce all'applicazione di creare un'istanza di migliaia di oggetti, risparmiando tempo e memoria.
Xamarin.Forms consente il ListView
riutilizzo delle celle tramite l'enumerazione ListViewCachingStrategy
, con i valori seguenti:
public enum ListViewCachingStrategy
{
RetainElement, // the default value
RecycleElement,
RecycleElementAndDataTemplate
}
Nota
La piattaforma UWP (Universal Windows Platform) (UWP) ignora la strategia di memorizzazione nella cache, perché usa sempre la RetainElement
memorizzazione nella cache per migliorare le prestazioni. Pertanto, per impostazione predefinita, si comporta come se fosse applicata la RecycleElement
strategia di memorizzazione nella cache.
RetainElement
La RetainElement
strategia di memorizzazione nella cache specifica che ListView
genererà una cella per ogni elemento nell'elenco ed è il comportamento predefinito ListView
. Deve essere usato nelle circostanze seguenti:
- Ogni cella ha un numero elevato di associazioni (20-30+).
- Il modello di cella cambia frequentemente.
- Il test rivela che la strategia di
RecycleElement
memorizzazione nella cache comporta una riduzione della velocità di esecuzione.
È importante riconoscere le conseguenze della strategia di RetainElement
memorizzazione nella cache quando si lavora con celle personalizzate. Qualsiasi codice di inizializzazione delle celle dovrà essere eseguito per ogni creazione di cella, che può essere più volte al secondo. In questa circostanza, le tecniche di layout eseguite correttamente in una pagina, come l'uso di più istanze annidate StackLayout
, diventano colli di bottiglia delle prestazioni quando vengono configurati e eliminati definitivamente in tempo reale mentre l'utente scorre.
RecycleElement
La RecycleElement
strategia di memorizzazione nella cache specifica che ListView
tenterà di ridurre al minimo il footprint di memoria e la velocità di esecuzione riciclando le celle dell'elenco. Questa modalità non offre sempre un miglioramento delle prestazioni e i test devono essere eseguiti per determinare eventuali miglioramenti. Tuttavia, è la scelta preferita e deve essere usata nelle circostanze seguenti:
- Ogni cella ha un numero ridotto o moderato di associazioni.
- Ogni cella
BindingContext
definisce tutti i dati delle celle. - Ogni cella è in gran parte simile, con il modello di cella che non cambia.
Durante la virtualizzazione la cella avrà aggiornato il contesto di associazione e pertanto, se un'applicazione usa questa modalità, deve assicurarsi che gli aggiornamenti del contesto di associazione vengano gestiti in modo appropriato. Tutti i dati relativi alla cella devono provenire dal contesto di associazione o possono verificarsi errori di coerenza. Questo problema può essere evitato usando il data binding per visualizzare i dati delle celle. In alternativa, i dati delle celle devono essere impostati nell'override OnBindingContextChanged
, anziché nel costruttore della cella personalizzata, come illustrato nell'esempio di codice seguente:
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;
}
}
}
Per altre informazioni, vedere Binding Context Changes.For more information, see Binding Context Changes.
In iOS e Android, se le celle usano renderer personalizzati, devono assicurarsi che la notifica di modifica delle proprietà sia implementata correttamente. Quando le celle vengono riutilizzate, i valori delle proprietà cambiano quando il contesto di associazione viene aggiornato a quello di una cella disponibile, con PropertyChanged
eventi generati. Per altre informazioni, vedere Personalizzazione di un elemento ViewCell.
RecycleElement con DataTemplateSelector
Quando un ListView
oggetto usa un DataTemplateSelector
oggetto per selezionare un DataTemplate
oggetto , la strategia di memorizzazione nella cache non memorizza nella RecycleElement
cache DataTemplate
s. Viene invece selezionato un oggetto DataTemplate
per ogni elemento di dati nell'elenco.
Nota
La RecycleElement
strategia di memorizzazione nella cache ha un prerequisito, introdotto nella Xamarin.Forms versione 2.4, che quando viene richiesto a un oggetto DataTemplateSelector
di selezionare che DataTemplate
ognuno DataTemplate
deve restituire lo stesso ViewCell
tipo. Ad esempio, dato un ListView
oggetto con che DataTemplateSelector
può restituire MyDataTemplateA
(dove MyDataTemplateA
restituisce un ViewCell
di tipo MyViewCellA
) o MyDataTemplateB
(dove MyDataTemplateB
restituisce un ViewCell
di tipo MyViewCellB
), quando MyDataTemplateA
viene restituito deve restituire MyViewCellA
o verrà generata un'eccezione.
RecycleElementAndDataTemplate
La RecycleElementAndDataTemplate
strategia di memorizzazione nella cache si basa sulla RecycleElement
strategia di memorizzazione nella cache assicurando inoltre che quando un ListView
oggetto usa per DataTemplateSelector
selezionare un DataTemplate
oggetto , DataTemplate
s viene memorizzato nella cache in base al tipo di elemento nell'elenco. Pertanto, DataTemplate
s viene selezionato una volta per ogni tipo di elemento, anziché una volta per ogni istanza di elemento.
Nota
La RecycleElementAndDataTemplate
strategia di memorizzazione nella cache ha un prerequisito che deve DataTemplate
essere DataTemplate
utilizzato dal DataTemplateSelector
costruttore che accetta un oggetto Type
.
Impostare la strategia di memorizzazione nella cache
Il ListViewCachingStrategy
valore di enumerazione viene specificato con un ListView
overload del costruttore, come illustrato nell'esempio di codice seguente:
var listView = new ListView(ListViewCachingStrategy.RecycleElement);
In XAML impostare l'attributo CachingStrategy
come illustrato nel codice XAML seguente:
<ListView CachingStrategy="RecycleElement">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
...
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Questo metodo ha lo stesso effetto dell'impostazione dell'argomento strategia di memorizzazione nella cache nel costruttore in C#.
Impostare la strategia di memorizzazione nella cache in un controllo ListView sottoclassato
L'impostazione dell'attributo CachingStrategy
da XAML in una sottoclassata ListView
non produrrà il comportamento desiderato, perché non esiste alcuna CachingStrategy
proprietà in ListView
. Inoltre, se XAMLC è abilitato, verrà generato il messaggio di errore seguente: Nessuna proprietà, proprietà associabile o evento trovato per 'CachingStrategy'
La soluzione a questo problema consiste nel specificare un costruttore nella sottoclassata ListView
che accetta un ListViewCachingStrategy
parametro e lo passa nella classe base:
public class CustomListView : ListView
{
public CustomListView (ListViewCachingStrategy strategy) : base (strategy)
{
}
...
}
È quindi possibile specificare il ListViewCachingStrategy
valore di enumerazione da XAML usando la x:Arguments
sintassi :
<local:CustomListView>
<x:Arguments>
<ListViewCachingStrategy>RecycleElement</ListViewCachingStrategy>
</x:Arguments>
</local:CustomListView>
Suggerimenti sulle prestazioni di ListView
Esistono molte tecniche per migliorare le prestazioni di un oggetto ListView
. I suggerimenti seguenti possono migliorare le prestazioni di ListView
- Associare la
ItemsSource
proprietà a unaIList<T>
raccolta anziché a unaIEnumerable<T>
raccolta, perchéIEnumerable<T>
le raccolte non supportano l'accesso casuale. - Usare le celle predefinite (ad esempio
TextCell
/SwitchCell
) anzichéViewCell
ogni volta che è possibile. - Usare un minor numero di elementi. Si consideri ad esempio l'uso di una singola
FormattedString
etichetta anziché di più etichette. ListView
Sostituire con unTableView
oggetto quando vengono visualizzati dati non omogenei, ovvero dati di tipi diversi.- Limitare l'uso del
Cell.ForceUpdateSize
metodo . Se sovrautilizzata, le prestazioni risulteranno ridotte. - In Android evitare di impostare la visibilità o il colore del separatore di riga di un
ListView
oggetto dopo che è stata creata un'istanza, in quanto comporta una riduzione delle prestazioni elevata. - Evitare di modificare il layout della cella in base a
BindingContext
. La modifica del layout comporta grandi costi di misurazione e inizializzazione. - Evitare gerarchie di layout annidate in modo approfondito. Usare
AbsoluteLayout
oGrid
per ridurre l'annidamento. - Evitare specifiche
LayoutOptions
diverse daFill
(Fill
è la più economica da calcolare). - Evitare di inserire un oggetto
ListView
all'interno di perScrollView
i motivi seguenti:ListView
Implementa il proprio scorrimento.- L'oggetto
ListView
non riceverà alcun movimento, perché verrà gestito dall'oggetto padreScrollView
. ListView
Può presentare un'intestazione e un piè di pagina personalizzati che scorre con gli elementi dell'elenco, offrendo potenzialmente la funzionalitàScrollView
usata da . Per altre informazioni, vedere Intestazioni e piè di pagina.
- Prendere in considerazione un renderer personalizzato se è necessaria una progettazione specifica e complessa presentata nelle celle.
AbsoluteLayout
ha il potenziale di eseguire layout senza una singola chiamata di misura, rendendolo estremamente efficiente. Se AbsoluteLayout
non è possibile usare , prendere in considerazione RelativeLayout
. Se si usa RelativeLayout
, il passaggio diretto dei vincoli sarà notevolmente più veloce rispetto all'uso dell'API dell'espressione. Questo metodo è più veloce perché l'API dell'espressione usa JIT e in iOS l'albero deve essere interpretato, che è più lento. L'API delle espressioni è adatta per i layout di pagina in cui è necessaria solo per il layout iniziale e la rotazione, ma in , dove ListView
viene eseguita costantemente durante lo scorrimento, le prestazioni vengono ridotte.
La creazione di un renderer personalizzato per una ListView
o le relative celle è un approccio per ridurre l'effetto dei calcoli di layout sulle prestazioni di scorrimento. Per altre informazioni, vedere Personalizzazione di un controllo ListView e Personalizzazione di un controllo ViewCell.