Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

RecyclerView: liste di nuova generazione

Conoscere ed utilizzare RecyclerView e CardView, due widget introdotti per ottimizzare la visualizzazione dei dati in forma di lista sulle app Android.
Conoscere ed utilizzare RecyclerView e CardView, due widget introdotti per ottimizzare la visualizzazione dei dati in forma di lista sulle app Android.
Link copiato negli appunti

Le app spesso mostrano dati in sequenza, in griglia o in qualche altra forma strutturata. Qualunque sia il loro significato e provenienza, una delle prime necessità del programmatore è visualizzarli tramite Adapter e strumenti come la ListView. Imparare a farlo non è proibitivo ma l'importante è non trascurare necessari accorgimenti di ottimizzazione per salvaguardare le prestazioni dell'applicazione. Nasce per questo la RecyclerView, un modo efficiente per gestire una problematica tanto comune. Questa lezione ne mostra l'utilizzo.

L'esempio

L'esempio che vedremo di seguito non riguarda il NewsReader che realizzeremo come prodotto finale di questa guida. Anche in questo caso, acquisiremo alcune nozioni propedeutiche che verranno innestate nell'esempio del capitolo precedente, quello riguardante le Toolbar. Utilizzeremo i nuovi widget nati per il Material Design, RecyclerView e CardView, per visualizzare un elenco di notizie. Le informazioni proverranno da una classe DataProvider e saranno prelevabili come oggetti di classe Content tramite il metodo statico getContentsByCategory. Quello che segue è il risultato:

Figura 1. RecyclerView e CardView
RecyclerView e CardView

La RecyclerView è stata introdotta nella support library quindi per prima cosa dovremo aggiornare il file build.gradle per risolvere le dipendenze di cui abbiamo bisogno:

dependencies
{
   compile fileTree(dir: 'libs', include: ['*.jar'])
   compile 'com.android.support:appcompat-v7:22.2.0'
   compile 'com.android.support:design:22.2.0'
   compile 'com.android.support:cardview-v7:21.0.+'
   compile 'com.android.support:recyclerview-v7:21.0.+'
}

Per prima cosa, la RecyclerView va inserita nel layout (file: /res/layout/activity_main.xml):

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/main_content"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">
    <!-- OMISSIS: codice per includere la Toolbar-->
    <android.support.v7.widget.RecyclerView
        android:id="@+id/recyclerview"
        android:scrollbars="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
</LinearLayout>

Le singole righe che mostrerà saranno invece realizzate tramite un altro nuovo widget, la CardView. Il layout dei singoli elementi da mostrare sarà incluso nel file /res/layout/row.xml:

<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="5dp"
    card_view:cardCornerRadius="15dp"
    card_view:cardBackgroundColor="#FFEA00"
    card_view:cardElevation="7dp"
    >
        <TextView
            android:id="@+id/title"
            android:gravity="center"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            />
</android.support.v7.widget.CardView>

CardView eredita dalla classe FrameLayout ed è predisposta per mostrare in maniera consistente i contenuti nelle applicazioni. Dispone di elementi particolarmente utili, definibili tramite gli attributi del namespace che chiameremo card_view: angoli arrotondati (cardCornerRadius), ombre, configurabili tramite il parametro cardElevation ed altro ancora.

Anche la RecyclerView ha bisogno di un Adapter per lavorare e questo è uno degli aspetti più interessanti che vedremo: qui i principi di efficienza del nuovo widget prendono forma.

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
    private List<DataProvider.Content> mDataset;
    public static class ViewHolder extends RecyclerView.ViewHolder {
        public TextView title;
        public ViewHolder(View v)
        {
            super(v);
            title= (TextView) v.findViewById(R.id.title);
        }
    }
    public MyAdapter(List<DataProvider.Content> myDataset) {
        mDataset = myDataset;
    }
    @Override
    public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
    {
        View v = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.row, parent, false);
        ViewHolder vh = new ViewHolder(v);
        return vh;
    }
    @Override
    public void onBindViewHolder(ViewHolder holder, int position)
    {
        DataProvider.Content tmp=mDataset.get(position);
        holder.title.setText(tmp.getTitle());
    }
    @Override
    public int getItemCount() {
        return mDataset.size();
    }
}

L'Adapter che creiamo estende una classe definita nell'ambito della RecyclerView. Un elemento che spicca è l'obbligatorietà che ha assunto il pattern ViewHolder. Tale concetto è una pratica fortemente consigliata dalla documentazione ufficiale al fine di ridurre al minimo le invocazioni al metodo findViewById, piuttosto costoso se ripetuto troppo spesso.
La RecyclerView ricicla il più possibile le view che crea per mostrare gli elementi, ed il ViewHolder conserva i riferimenti ai widget interni ad ogni elemento.
I metodi onCreateViewHolder e onBindViewHolder, rispettivamente, rappresentano il momento in cui un elemento della RecyclerView viene creato e il momento in cui vengono recuperati i riferimenti ai suoi elementi interni da popolare con i nuovi dati.

Infine, non resta altro che fare incontrare tutti gli elementi appena prodotti nell'onCreate dell'Activity.

@Override
    protected void onCreate(Bundle savedInstanceState)
    {
        // OMISSIS: configurazione layout e Toolbar
	mRecyclerView = (RecyclerView) findViewById(R.id.recyclerview);
        mRecyclerView.setHasFixedSize(true);
        mLayoutManager = new LinearLayoutManager(this);
        mRecyclerView.setLayoutManager(mLayoutManager);
        mAdapter = new MyAdapter(DataProvider.getContentsByCategory(DataProvider.GREEN_CATEGORY));
        mRecyclerView.setAdapter(mAdapter);
    }

Nelle precendenti righe di codice, la RecyclerView non riceve solo il riferimento all'Adapter tramite il tradizionale metodo setAdapter ma anche la configurazione del LayoutManager. Questo è un elemento nuovo che permette di specificare come vogliamo che gli elementi appaiano. Nel nostro caso usiamo un LinearLayoutManager che farà comportare il widget come una ListView, ma in alternativa avremmo potuto usare GridLayoutManager o StaggeredLayoutManager.
Ad esempio, usando la seguente espressione:

mLayoutManager = new GridLayoutManager(this,2);

il risultato sarebbe questo:

Figura 2. Effetto del GridLayoutManager
Effetto del GridLayoutManager

Il codice d’esempio visto fin qui è allegato a questa lezione, e liberamente scaricabile.

Ti consigliamo anche