La pull to refresh è una gesture molto comune, utilizzata nelle applicazioni che solitamente hanno un feed di contenuti che l’ utente vuole aggiornare.

In Android hanno aggiunto un api per implementare molto velocemente e facilmente questa gesture nelle nostre app.

Per avere un esempio completo, potete far riferimento a questo progetto su GitHub:
fork-me-on-github

Vediamo subito quindi i passaggi da seguire per implementare questa gesture:

1. Wrappare il layout “aggiornabile” con un SwipeRefreshLayout:

    <android.support.v4.widget.SwipeRefreshLayout
        android:id="@+id/swipe_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <ListView
            android:id="@+id/listview"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"/>
    </android.support.v4.widget.SwipeRefreshLayout>

Solitamente si tratta di una listview, o di una più recente RecyclerView, ma comunque sempre una lista di contenuti.

2. Prendere la referenza, e creare un listener

Prendiamo la referenza allo SwipeRefreshLayout nell’ OnCreate della nostra Activity:

@Override
protected void onCreate(Bundle savedInstanceState)
{
    ...
    mSwipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipe_container);
    ...
}

3. Associamo un OnRefreshListener:

In questo caso, ho scelto di far implementare l’ interfaccia SwipeRefreshLayout.OnRefreshListener direttamente alla mia activity:

public class MainActivity extends AppCompatActivity implements SwipeRefreshLayout.OnRefreshListener
{
    ...
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        ...
        mSwipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipe_container);
        mSwipeRefreshLayout.setOnRefreshListener(this);
        ...
    }
    ...     
}

Implementiamo poi il metodo richiesto

Da Android Studio, per avere la dichiarazione dei metodi da implementare di un’ interfaccia usiamo lo shortcut ctrl+i

public class MainActivity extends AppCompatActivity implements SwipeRefreshLayout.OnRefreshListener
{
    ...
    @Override
    public void onRefresh()
    {
    }
    ...
}

All’ interno di questo metodo dobbiamo essenzialmente fare due cose:

  1. Aggiorniamo i dati: Eseguiamo il refresh dei dati. Solitamente (ma non per forza) svuotiamo le varie views, e le ripopoliamo con i contenuti freschi.
  2. Richiamiamo il metodo mSwipeRefreshLayout .setRefreshing(false);per indicare che il refresh è completato.

Pro e contro

Se scegliamo di implementare lo SwipeToRefresh usando la libreria di supporto, allora abbiamo retrocompatibilità garantita fino alle api level 7.

L’ utilizzo di questa bellissima gesture per aggiornare i contenuti è stata ultimamente presa a dibattito per un motivo: quando sviluppiamo un’ applicazione che sfrutta la rete, non deve essere l’ utente a richiedere contenuti ma deve essere l’ app stessa a fornirglieli prima ancora che lui sappia di volerli.

Un esempio concreto è Gmail desktop: il refresh delle nuove mail avviene in automatico, non abbiamo bisogno di aggiornare la pagina per leggere le nuove mail ma queste vengono automaticamente caricate non appena sono disponibili.

Questo secondo molti è il corretto workflow che dovrebbe seguire anche un app per telefoni (dove l’ utente è distratto e và ancora di più di fretta).

Per fare una cosa del genere però, abbiamo bisogno di un server e di un servizio di Messaging (ad esempio GCM) che rendono l’ architettura lato server molto più complessa.

Quando l’ utente esegue l’ aggiornamento manuale poi, si ritrova in un punto della lista di contenuti che non sa quanto è distante da dove si trovava in precedenza.

Quanti contenuti sono stati aggiunti?

Un esempio interessante è quello di Twitter: carca i nuovi contenuti sopra a quelli attuali in modo che l’ utente non perda il riferimento alla posizione precedente e si renda conto di quali siano i nuovi tweets.

Sono stati aggiunti contenuti?

Dovremmo informare l’ utente anche nel caso in cui sia stato interrogato il server, ma non abbiamo trovato nuovi contenuti da mostrare.