2010-03-26 2 views
5

Ho un listview con 200 articoli. Io uso una vista personalizzata per ogni riga. C'è un codice che richiede un po 'di tempo per calcolare, e per questo la lista si blocca sullo scrolling e carica lentamente (2-3sec).Come programmare un lavoro pesante per la visualizzazione successiva per Listviews?

Ho sottoclasse SimpleCursorAdapter e utilizzo Filterable e SectionIndexer.

Ho in mente di visualizzare inizialmente il nome del record e di inserire in un thread il calcolo, e verrà visualizzato più tardi una volta terminato.

Come si respinge un po 'di lavoro e in seguito si aggiorna la list list per includere i dati calcolati? Questo dovrebbe apparire al volo senza l'interazione dell'utente.

risposta

2

Dal android l'interfaccia utente di Android è singlethreaded verrà bloccato ogni volta che si esegue una lunga operazione.

Si potrebbe fare regolare threading Java e hanno un Handler() nella classe principale dell'interfaccia utente che è possibile alimentare di nuovo le informazioni in. Ma ..

Il modo più semplice sarebbe quella di creare un AsyncTask(). Sono fili java con un leggero cambiamento. Possono eseguire un'operazione UI prima/dopo il calcolo principale. Così, per esempio:

private class AndroidThread extends AsyncTask { 
     protected Object doInBackground(Object... params) { 
      return result; 
     } 

     protected void onPostExecute(Object result) { 
      // do things here with the result of the doInBackground function 
      // Like: "UiElement"."performTask(result)" 
     } 
} 

Per ulteriori informazioni su AsyncTask see this

1

Hmm, domanda interessante. Ecco alcuni pensieri rapidi:

1) Inserire i valori che possono essere recuperati direttamente, ovvero il nome del record appena inserito, direttamente nell'elenco. Lasciare valori predefiniti, come "Caricamento in corso ...", per tutto ciò che potrebbe richiedere del tempo per il calcolo.

2) Creare un secondo thread per fare i calcoli, ma per assicurarsi che non calcola tutto usare ascoltatore onScrollStateChanged del ListView. Ciò consente di eseguire il lavoro in background solo quando l'elenco è inattivo o viene fatto scorrere lentamente tramite touch-scroll. In altre parole, non preoccuparti quando è in modalità 'fling' poiché le righe sarebbero passate molto tempo prima che i calcoli finissero.

3) Non sono del tutto sicuro di come è possibile accodare la fase di caricamento nella discussione. Si desidera avere solo un thread di caricamento - l'apertura di un nuovo thread per ogni riga sarebbe piuttosto disordinata e anche inutile in quanto i telefoni non sono multicore - ma ciò significa che il thread deve disporre di un sistema di accodamento. Quello che voglio dire è che il thread deve essere consapevole di quali file sono in attesa di calcolo, ma non ho pensato a come lo faresti ancora. Tuttavia, questo dovrebbe anche essere legato a quali file sono visibili. Non c'è alcun punto nel thread che calcola le informazioni per le righe passate in passato nella lista.

4) Ogni volta che il thread di caricamento termina una determinata riga, è possibile chiamare notifyDatasetChanged() sull'adattatore di elenco. Questo potrebbe diventare un po 'pesante se ListView tenta di aggiornare i suoi dati per ogni riga piuttosto che solo quelli visibili, ma dovresti sperimentare per vedere.

Spero che queste idee aiutino un po '!


In risposta al commento: Supponendo che si sta chiedendo quando una riga è visibile, è possibile farlo mediante l'attuazione di ListView.OnScrollListener. Ho preso ispirazione da ApiDemos List13, ma qui ci sono i bit rilevanti di codice:

public class YourClass extends ListActivity implements ListView.OnScrollListener { 
    public void onCreate(Bundle sIS){ 
     (...) 
     // Note, you may have to write your own list adapter, extending BaseAdapter 
     // See List13 in Api Demos for an example if you're not sure how to do that 
     setListAdapter(yourImageAdapter); 
     getListView().setOnScrollListener(this); 
    } 

    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, 
      int totalItemCount) { 
     Log.d(LOG_TAG, "onScroll, firstVisibleItem = " + firstVisibleItem + 
       ", visibleItemCount = " + visibleItemCount 
       + ", totalItemCount = " + totalItemCount); 
    } 

    public void onScrollStateChanged(AbsListView view, int scrollState) { 
     Log.d(LOG_TAG, "onScrollStateChanged called, scrollState = " + scrollState); 
     switch (scrollState) { 
     case OnScrollListener.SCROLL_STATE_IDLE: 
      int first = view.getFirstVisiblePosition(); 
      int count = view.getChildCount(); 

      Log.d(LOG_TAG, "first = " + first + ", count = " + count); 

      break; 
     case OnScrollListener.SCROLL_STATE_TOUCH_SCROLL: 
      //Scrolling with the finger touching the screen 
      break; 

     case OnScrollListener.SCROLL_STATE_FLING: 
      // User 'threw' the list up or down and it's scrolling rapidly 
      break; 
     } 
    } 
} 

che ti dice tutto ciò che riguarda la vostra lista: che si tratti di scorrimento, ciò che è visibile, ecc Se si utilizza che con il filo di carico solo eseguire il lavoro in background per le righe visibili, che dovrebbe aiutare a ridurre i costi aggiuntivi non necessari.

Un altro punto su BaseAdapter: Non ho provato con qualsiasi altra forma di adattatore di lista in modo forse è lo stesso con tutti loro, ma una cosa molto utile con BaseAdapter è che consente di gestire l' 'inflazione' di ogni fila individualmente. Ogni volta che la lista sta per mostrare una nuova riga, viene chiamato getView. Puoi inserire codice personalizzato lì per fare cose come mettere "Caricamento in corso ..." se le informazioni non sono ancora state calcolate, o in realtà visualizzarle se lo sono.

A proposito, che cosa stai effettivamente calcolando in questa lista che impiega così tanto tempo?

+0

Come posso rilevare quando una riga è dipinto? – Pentium10

+0

Ho modificato la mia risposta per fornire ulteriori informazioni. –

+0

Ho una lista di contatti, calcolo l'imminente compleanno del contatto e la sua età (età display: 21 in 7 mesi) – Pentium10