Domanda

Riepilogo: Cercando di aggiungere dinamicamente righe di titolo ad un ListView tramite un wrapper adattatore personalizzato. ListView sta avendo problemi a mantenere la posizione di scorrimento in sincronia. progetto demo eseguibile fornito.

Vorrei aggiungere dinamicamente elementi a un elenco in base ai valori in un CursorAdapter, diverse posizioni in vista di ciò che l'utente sta visualizzando. Per fare questo, ho un adattatore che avvolge il CursorAdapter e mantiene il nuovo contenuto indicizzato in uno SparseArray. Le esigenze ListView da aggiornare quando gli elementi vengono aggiunti alla scheda personalizzata, ma ho incontrato un sacco di insidie ??cercando di ottenere che al lavoro e mi piacerebbe qualche consiglio.

Il progetto demo può essere scaricato qui: DynamicSectionedList.zip

Nella demo, i titoli vengono aggiunti in modo dinamico, cercando avanti di 10 posti per trovare la posizione corretta in cui le voci di elenco passare alla lettera successiva. Ogni implementazione di notifyDataSetChanged ha problemi come descritto:

Demo 1 Questa demo mostra l'importanza di notifyDataSetChanged (). Cliccando nulla, l'applicazione si blocca. Ciò è dovuto a qualche controllo sanità mentale in ListView ... mItemCount != adapter.getItemCount(). Morale è, abbiamo bisogno di notificare l'elenco di dati che è cambiato.

Demo 2 Il passo successivo naturale è quello di informare il ListView di modifiche in caso di modifiche. Purtroppo, così facendo mentre il ListView scorre saldamente rompe tutte le interazioni contatto fino a quando l'applicazione passa dalla modalità di contatto. Avrete bisogno di "scroll lanciare" quanto basta per generare nuove voci al fine di notare questo. Toccando lo schermo non causerà il rotolo di fermarsi, e una volta fermato nessuno degli elementi della lista sarà cliccabile. Ciò è dovuto a un codice a if (!mDataChanged) { /* do very important stuff */ } AbsListView.onTouchEvent ().

Demo 3 Per risolvere questo problema, Demo 3 introduce una bandiera pendingChanges e gli utili adattatore personalizzato un notifyDataSetChangedIfNeeded () che può essere chiamato dal ListView una volta che è entrato in uno stato "sicuro" per le modifiche. Il primo punto in cui devono essere comunicate le modifiche è in ListView.layoutChildren (), così ho calpestato quel metodo alla prima notifica di modifiche, se necessario, quindi chiamare attraverso. Fling passato almeno un titolo quindi fare clic su un elemento della lista.

Questo non del tutto funziona bene, anche se non sono del tutto sicuro perché. Toccando o la selezione di un elemento con la tastiera / trackball fa sì che la lista per aggiornare senza sincronizzare adeguatamente la vecchia posizione. Essa scorre in cima alla lista, che non è accettabile.

Demo 4 Il problema di scorrimento nella Demo 3 può essere conquistato, almeno in modalità touch. Con l'aggiunta di una chiamata a notifyDataSetChangedIfNeeded () sul touch down, la variazione dei dati avviene a prendere posto in un momento così che tutta l'interazione touch funziona come previsto e la posizione lista è correttamente sincronizzato.

Tuttavia, non riesco a trovare un analogo per che quando il dispositivo non è in modalità touch, per non parlare del fatto che sembra decisamente come un hack. L'elenco scorre quasi sempre torna, non riesco a scoprire che cosa induce a mantenere la posizione corretta di tanto in tanto.

Dal momento che Android mi sta combattendo ad ogni passo del cammino, mi sento come ci dovrebbe essere un approccio migliore. Si prega di provare la demo, se le correzioni possono essere applicate a farlo funzionare che sarebbe grande!

Molte grazie a tutti coloro che possono guardare in questo, spero che se siamo in grado di ottenere il codice di lavoro sarà utile per gli altri cercando di realizzare la stessa ottimizzazione per liste con intestazioni.

È stato utile?

Soluzione

Il problema principale con l'approccio presentato in precedenza era che l'insieme di dati veniva modificata direttamente dall'interno di codice eseguito dalle superclassi. Completando i titoli in GetView () stavo cambiando i dati in quello che potrebbe essere il corso di un'operazione o di uno stato "non sicuro" nelle superclassi. Questo è il motivo per cui tutte le interazioni tocco rotto quando onNotifyDataSetChanged è stato chiamato durante una pergamena scappatella. I dati devono essere aggiunti da una fonte esterna, non dall'interno metodi dell'adattatore.

che può essere fatto utilizzando un Handler o AsyncTask per aggiungere le intestazioni all'adattatore e chiamare il notifyDataSetChanged. Questi saranno eseguite su un thread UI e non interferiscono con lo stato superclasse. Grazie a esempio EndlessAdapter di CommonsWare per l'introduzione del concetto di AsyncTask per aggiungere i dati a un elenco.

L'onTouchEvent () e layoutChildren () hack non erano più necessari dopo aver fatto che il cambiamento.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top