Utilizzare un ArrayAdapter con le ListView in Android

Ottimizzare l’utilizzo e la visualizzazione delle liste di elementi in Android riciclando le righe non visualizzate con il pattern ViewHolder

In Android per visualizzare una lista scrollabile di elementi viene utilizzato un oggetto di tipo ListView popolato tramite un Adapter. In molti casi viene utilizzato un ArrayAdapter che si pone tra la ListView (rappresentazione dei dati) e un ArrayList (dati da visualizzare) che ha il compito di convertire gli elementi presenti nell’ArrayList in oggetti View da visualizzare nella lista.

L’adapter consente di automatizzare il processo di conversione da un oggetto dell’array ad un oggetto della lista ma quando una ListView viene collegata ad un adapter vengono instanziate tutte le righe visualizzabili nella schermata. Ecco come settare un adapter ad una ListView in modo da visualizzare gli elementi contenuti nell’array:

  // Costruisco il data source
  ArrayList arrayOfUsers = new ArrayList();
  // Creo un adapter per convertire l'array nelle view
  UsersAdapter adapter = new UsersAdapter(this, arrayOfUsers);
  // Setto l'adapter alla ListView
  ListView listView = (ListView) findViewById(R.id.lvItems);
  listView.setAdapter(adapter);

A questo punto i dati saranno direttamente popolati e visualizzati sullo schermo. Per aggiungere nuovi elementi basterà scrivere:

  // Aggiungi un elemento all'adapter
  User newUser = new User("Nathan", "San Diego");
  adapter.add(newUser);
  // Oppure aggiungendo un'intera collezione, ad esempio se i dati sono in JSON li convertiamo in un ArrayList
  ArrayList newUsers = User.fromJson(jsonArray)
  adapter.addAll(newUsers);

I dati saranno aggiunti alla lista visualizzati che può essere svuotata con:

  adapter.clear();

Grazie all’adapter, qualsiasi modifica sarà apportata ai dati sarà riportata nella lista visualizzata.

Riutilizzare le righe della ListView in Android per prevenire un uso eccessivo di memoria

Quando l’utente scrolla una lista di elementi, di default in Android saranno create nuove righe ma quelle già presenti, mentre quelle non più visualizzabili resteranno in memoria pronte ad un uso successivo. Con questa tecnica utilizzando una lista con centinaia di elementi si corre il rischio che per poche righe visualizzate sullo schermo ci si ritrovi ad avere in memoria centinaia di elementi visualizzati in precedenza. Per ovviare a questo inconveniente è possibile riciclare le righe non più visualizzate che lasciano lo schermo con lo scroll dell’utente tenute in attesa in memoria.

Riciclare righe in una ListView Android

Per riciclare le righe in una ListView è possibile utilizzare il pattern ViewHolder che consente di migliorare le prestazioni che utilizza la cache per velocizzare le prestazioni durante il caricamento degli elementi:

  public class UsersAdapter extends ArrayAdapter {
    // Per la cache
    private static class ViewHolder {
      TextView name;
      TextView home;
    }

    public UsersAdapter(Context context, ArrayList users) {
      super(context, R.layout.item_user, users);
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
      // Prendi la posizione dell'elemento
      User user = getItem(position);

      // Controlla se esiste una view da riutilizzata, altrimenti facciamo un inflate con la view
      ViewHolder viewHolder; // Tag per salvare la view di ricerca

      if (convertView == null) {
        viewHolder = new ViewHolder();
        LayoutInflater inflater = LayoutInflater.from(getContext());
        convertView = inflater.inflate(R.layout.item_user, parent, false);
        viewHolder.name = (TextView) convertView.findViewById(R.id.tvName);
        viewHolder.home = (TextView) convertView.findViewById(R.id.tvHome);
        convertView.setTag(viewHolder);

      } else {
        viewHolder = (ViewHolder) convertView.getTag();
      }

      // Popola la view del template usando i dati
      viewHolder.name.setText(user.name);
      viewHolder.home.setText(user.hometown);

      // Ritorna la view completa da visualizzare sullo schermo
      return convertView;
    }
  }

Strutturando il codice in questo modo avremo che quando il numero massimo di righe visualizzabili sullo schermato viene raggiunto, il pattern ViewHolder è in grado di riciclare le view delle righe non visualizzate evitando di dover rieffettuare i findViewById() che risultano molto lenti. Nello specifico, per verificare se una View è stata riciclata effettuiamo il controllo if (convertView == null) e se è valorizzato possiamo riciclare la View cambiando i suoi valori senza doverne creare una completamente nuova. Tutto ciò è possibile grazie al metodo setTag() che consente di “attaccare” un qualsiasi oggetto ad un oggetto View.

Un’alternativa senza utilizzare direttamente con una sottoclasse il pattern ViewHolder è disponibile sul seguente articolo: Customizing Android ListView Rows by Subclassing

Questo articolo fa riferimento all’articolo di CodePath su GitHub.

Per approfondire Android ecco la guida completa completa: Guida Android.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *