Condividi tramite


Virtualizzazione dei dati in ListView e GridView

Nota
Per altri dettagli, vedere la sessione //build/ aumentare notevolmente le prestazioni quando gli utenti interagiscono con grandi quantità di dati in GridView e ListView.

Migliorare le prestazioni e il tempo di avvio di ListView e GridView tramite la virtualizzazione dei dati. Per la virtualizzazione dell'interfaccia utente, la riduzione degli elementi e l'aggiornamento progressivo degli elementi, vedere Ottimizzare le prestazioni di ListView e GridView per WinUI.

Un metodo di virtualizzazione dei dati è necessario per un set di dati così grande che non può o non deve essere archiviato in memoria contemporaneamente. Si carica una parte iniziale in memoria (da disco locale, rete o cloud) e si applica la virtualizzazione dell'interfaccia utente a questo set di dati parziale. In un secondo momento è possibile caricare i dati in modo incrementale o da punti arbitrari nel set di dati master (accesso casuale), su richiesta. L'eventuale virtualizzazione dei dati appropriata dipende da molti fattori.

  • Dimensioni del set di dati
  • Dimensioni di ogni elemento
  • Origine del set di dati (disco locale, rete o cloud)
  • Utilizzo complessivo della memoria dell'app WinUI

Nota Tenere presente che una funzionalità è abilitata per impostazione predefinita per ListView e GridView che visualizza gli oggetti visivi segnaposto temporanei durante la panoramica o lo scorrimento rapido dell'utente. Quando vengono caricati i dati, queste viste segnaposto vengono sostituite con il tuo template di elemento. È possibile disattivare la funzionalità impostando ListViewBase.ShowsScrollingPlaceholders su false, ma in tal caso è consigliabile usare l'attributo x:Phase per eseguire il rendering progressivo degli elementi nel modello di elemento. Vedere Aggiornare gli elementi ListView e GridView in modo progressivo.

Ecco altri dettagli sulle tecniche di virtualizzazione dei dati incrementali e ad accesso casuale.

Virtualizzazione incrementale dei dati

La virtualizzazione incrementale dei dati carica i dati in sequenza. Un controllo ListView che usa la virtualizzazione incrementale dei dati può essere usato per visualizzare una raccolta di un milione di elementi, ma inizialmente vengono caricati solo 50 elementi. Quando l'utente esegue la panoramica o lo scorrimento, vengono caricati i 50 successivi. Quando gli elementi vengono caricati, il pollice della barra di scorrimento diminuisce di dimensioni. Per questo tipo di virtualizzazione dei dati si scrive una classe di origine dati che implementa queste interfacce.

Un'origine dati simile a questa è un elenco in memoria che può essere esteso continuamente. Il controllo degli elementi richiederà elementi utilizzando l'indicizzatore standard IList e la proprietà 'Count'. Il conteggio deve rappresentare il numero di elementi in locale, non la dimensione effettiva del set di dati.

Quando il controllo elementi si avvicina alla fine dei dati esistenti, chiama ISupportIncrementalLoading.HasMoreItems. Se si restituisce true, chiama ISupportIncrementalLoading.LoadMoreItemsAsync, passando un numero consigliato di elementi da caricare. A seconda della posizione in cui si caricano i dati da (disco locale, rete o cloud), è possibile scegliere di caricare un numero diverso di elementi rispetto a quanto indicato. Ad esempio, se il servizio supporta batch di 50 elementi, ma il controllo elementi richiede solo 10, è possibile caricare 50. Caricare i dati dal back-end, aggiungerli all'elenco e generare una notifica di modifica tramite INotifyCollectionChanged o IObservableVector<T> in modo che il controllo elementi conosca i nuovi elementi. Restituisce anche un conteggio degli elementi effettivamente caricati. Se si caricano meno elementi di quanto consigliato o se il controllo degli elementi è stato spostato o scorre ulteriormente nel frattempo, la fonte dati sarà nuovamente richiesta per ulteriori elementi e il ciclo continua. ISupportIncrementalLoading rimane disponibile in Windows App SDK, quindi puoi usare lo stesso modello di caricamento incrementale in un'app WinUI.

Virtualizzazione dei dati ad accesso casuale

La virtualizzazione dei dati ad accesso casuale consente il caricamento da un punto arbitrario nel set di dati. Un ListView che usa la virtualizzazione ad accesso casuale dei dati per visualizzare una raccolta di un milione di elementi può caricare elementi da 100.000 a 100.050. Se l'utente passa quindi all'inizio dell'elenco, il controllo carica gli elementi da 1 a 50. In ogni momento, il pollice della barra di scorrimento indica che ListView contiene un milione di elementi. La posizione del pollice della barra di scorrimento è relativa alla posizione in cui si trovano gli elementi visibili nell'intero set di dati della raccolta. Questo tipo di virtualizzazione dei dati può ridurre significativamente i requisiti di memoria e i tempi di caricamento per la raccolta. Per abilitarla, è necessario scrivere una classe di origine dati che recupera i dati su richiesta, gestisce una cache locale e implementa queste interfacce.

IItemsRangeInfo fornisce informazioni sugli elementi usati attivamente dal controllo. Il controllo items chiama questo metodo ogni volta che la visualizzazione cambia e include questi due set di intervalli.

  • Set di elementi presenti nel riquadro di visualizzazione.
  • Set di elementi non virtualizzati usati dal controllo che potrebbero non trovarsi nel riquadro di visualizzazione.
    • Un buffer di elementi attorno alla finestra di visualizzazione, gestito dagli elementi stessi, in modo da rafforzare la fluidità del tocco.
    • Elemento messo a fuoco.
    • Primo elemento.

Implementando IItemsRangeInfo, l'origine dati sa quali elementi devono essere recuperati e memorizzati nella cache e quando eliminare i dati dalla cache che non sono più necessari. IItemsRangeInfo usa oggetti ItemIndexRange per descrivere un set di elementi in base al relativo indice nell'insieme. In questo modo si evitano i puntatori agli elementi, che potrebbero non essere corretti o stabili. IItemsRangeInfo è progettato per essere usato solo da una singola istanza di un controllo elementi perché si basa sulle informazioni sullo stato per tale controllo elementi. Se più controlli di elemento devono accedere agli stessi dati, è necessaria un'istanza separata dell'origine dei dati per ognuno. Possono condividere una cache comune, ma la logica da eliminare dalla cache sarà più complessa. IItemsRangeInfo rimane disponibile in Windows App SDK, quindi le stesse tecniche di memorizzazione nella cache ad accesso casuale si applicano ai controlli WinUI.

Ecco la strategia di base per la sorgente dati della virtualizzazione con accesso casuale.

  • Quando viene richiesto un elemento
    • Se è disponibile in memoria, allora restituiscilo.
    • Se non lo possiedi, restituisci null o un elemento segnaposto.
    • Usare la richiesta per un elemento (o le informazioni sull'intervallo di IItemsRangeInfo) per sapere quali elementi sono necessari e recuperare i dati per gli elementi dal back-end in modo asincrono. Dopo aver recuperato i dati, generare una notifica di modifica tramite INotifyCollectionChanged o IObservableVector<T> in modo che il controllo elementi conosca il nuovo elemento.
  • (Facoltativamente) quando il riquadro del controllo degli elementi cambia, identifica gli elementi necessari dall'origine dati tramite l'implementazione di IItemsRangeInfo.

Oltre a ciò, la strategia per quando caricare gli elementi di dati, il numero di caricamento e gli elementi da conservare in memoria spetta all'applicazione. Alcune considerazioni generali da tenere presenti:

  • Effettuare richieste asincrone per i dati; non bloccare il thread dell'interfaccia utente.
  • Trova il punto ottimale nella dimensione dei lotti in cui si recuperano gli elementi. Preferisce contenuti concisi alle chiacchiere. Non così piccolo da effettuare troppe richieste di piccole dimensioni; non così grande da richiedere troppo tempo per essere recuperato.
  • Valutare il numero di richieste che si desidera avere in sospeso contemporaneamente. L'esecuzione di una alla volta è più semplice, ma potrebbe essere troppo lenta se il tempo di turnaround è elevato.
  • È possibile annullare le richieste di dati?
  • Se si usa un servizio ospitato, è previsto un costo per transazione?
  • Quale tipo di notifiche vengono fornite dal servizio quando i risultati di una query cambiano? Si saprà se un elemento viene inserito in corrispondenza dell'indice 33? Se il servizio supporta query basate su una chiave più offset, potrebbe essere migliore di usare solo un indice.
  • Quanto volete essere efficienti nel precaricamento degli elementi? Proverai a tenere traccia della direzione e della velocità dello scorrimento per stimare quali elementi sono necessari?
  • Quanto vuoi essere aggressivo nell'eliminare la cache? Si tratta di un compromesso tra memoria e esperienza.