18 Apr 2013 Android – Inserire una ListView con caricamenti parziali della lista sullo scorrimento
Se abbiamo una lista molto lunga e pesante da caricare sul nostro device Android, una delle soluzioni più comuni per risolvere il problema è quella di caricare porzioni di essa via via che si scorre con la visualizzazione.
Vi mostrerò di seguito il codice; prendete nota che si tratta di una lista “finita” di cui si conosce l’ammontare totale delle righe.
public class MyActivity extends Activity { //Numero massimo di righe da recuperare per volta private static final int NUM_RECORD_X_PAG = 50; //Variabile in cui mettere il numero totale delle righe della mia lista private int totalRows; private ListView listView; private MyAdapter listAdapter; private EndlessScrollListener listScrollListener; @Override protected void onCreate(Bundle savedInstanceState) { listView = (ListView) findViewById(R.id.listView); listAdapter = new MyAdapter(); listView.setAdapter(listAdapter); listScrollListener = new EndlessScrollListener(); listView.setOnScrollListener(listScrollListener); //Primo caricamento della lista LoadListTask task = new LoadListTask(); task.execute(); } //Adapter di appoggio per memorizzarsi la lista degli elementi visualizzati class MyAdapter extends BaseAdapter { List listDisplayed = new ArrayList(); public int getCount() { return listDisplayed.size(); } public Object getItem(int pos) { return listDisplayed.get(pos); } public long getItemId(int pos) { return pos; } public View getView(int pos, View v, ViewGroup p) { TextView view = new TextView(Test.this); view.setText(listDisplayed.get(pos)); return view; } public void setListDisplayed(List listDisplayed) { this.listDisplayed = listDisplayed; } public List getListDisplayed() { return this.listDisplayed; } } public class LoadListTask extends AsyncTask<Void, Void, List> { public LoadListTask() { } @Override protected List doInBackground(Void... params) { //Segnalo al mio listener di che sto facendo un caricamento listScrollListener.setLoading(true); int start = (listAdapter.getListDisplayed().size()); //Qui carico la lista parziale partendo da "start" per "NUM_RECORD_X_PAG" List partialList = getList(start, NUM_RECORD_X_PAG); return partialList; } @SuppressWarnings("unchecked") @Override protected void onPostExecute(List partialList) { //Alla mia lista attualmente visualizzata aggiungo la lista parziale appena caricata listAdapter.getListDisplayed().addAll(partialList); //Se ho caricato tutte le righe segnalo al listener di non lanciare più caricamenti if (listAdapter.getListDisplayed().size() == totalRows) listScrollListener.setFinished(true); else listScrollListener.setFinished(false); listAdapter.notifyDataSetChanged(); //Segnalo al mio listener di aver finito il caricamento listScrollListener.setLoading(false); } } public class EndlessScrollListener implements OnScrollListener { private boolean finished = false; private boolean loading = false; public EndlessScrollListener() { } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { boolean loadMore = firstVisibleItem + visibleItemCount >= totalItemCount; //Quando scrollo fino in fondo (loadMore), non c'è già un caricamento in corso (loading) e non ho già caricato tutta la lista (finished) if (loadMore && !finished && !loading && totalItemCount != 0) { LoadListTask task = new LoadListTask(); task.execute(); } } @Override public void onScrollStateChanged(AbsListView view, int scrollState) { } public boolean isFinished() { return finished; } public void setFinished(boolean finished) { this.finished = finished; } public boolean isLoading() { return loading; } public void setLoading(boolean loading) { this.loading = loading; } } }
Luca
Posted at 14:01h, 04 GiugnoMa il metodo getList(start, NUM_RECORD_X_PAG) dove lo trovo?
Giacomo Baccianti
Posted at 08:21h, 05 GiugnoQuel metodo non è presente in quanto semplicemente quello che ritorna è la lista dei valori da mostrare nella listView. Nel mio caso all’interno di quel metodo io faccio una chiamata al Database.
Luca
Posted at 17:04h, 06 GiugnoOk, ora è tutto funzionante. L’unico problema è che le righe della listView vengono visualizzate molto piccole, cosa che non succedeva prima. Penso che dipenda dall’adapter: quando lo creavo io facevo
mioAdapter = new ArrayAdapter (getApplicationContext(),android.R.layout.simple_list_item_1,lista);
mentre lei fa
listAdapter = new MyAdapter();
Potrebbe essere dovuto dal android.R.layout.simple_list_item_1 ??
Grazie in anticipo
Luca
Posted at 17:19h, 06 GiugnoNulla risolto, scusate il disturbo.
Il problema è un altro… che se scrollo tante volte su e giù si rallenta un sacco..