Afficher des listes paginées

Ce guide s'appuie sur la présentation de la bibliothèque Paging, qui explique comment présenter des listes d'informations aux utilisateurs dans l'interface utilisateur de votre application, en particulier lorsque ces informations changent.

Connecter votre UI à votre modèle de vue

Vous pouvez connecter une instance de LiveData<PagedList> à un PagedListAdapter, comme indiqué dans l'extrait de code suivant :

Kotlin

class ConcertActivity : AppCompatActivity() {
    private val adapter = ConcertAdapter()

    // Use the 'by viewModels()' Kotlin property delegate
    // from the activity-ktx artifact
    private val viewModel: ConcertViewModel by viewModels()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState);
        viewModel.concerts.observe(this, Observer { adapter.submitList(it) })
    }
}

Java

public class ConcertActivity extends AppCompatActivity {
    private ConcertAdapter adapter = new ConcertAdapter();
    private ConcertViewModel viewModel;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        viewModel = new ViewModelProvider(this).get(ConcertViewModel.class);
        viewModel.concertList.observe(this, adapter::submitList);
    }
}

Lorsque les sources de données fournissent de nouvelles instances de PagedList, l'activité envoie ces objets à l'adaptateur. L'intégration de PagedListAdapter définit le mode de calcul des mises à jour et gère automatiquement la pagination et la vérification différentielle ("diffing") des listes. ViewHolder ne doit donc être lié qu'à un élément donné :

Kotlin

class ConcertAdapter() :
        PagedListAdapter<Concert, ConcertViewHolder>(DIFF_CALLBACK) {
    override fun onBindViewHolder(holder: ConcertViewHolder, position: Int) {
        val concert: Concert? = getItem(position)

        // Note that "concert" is a placeholder if it's null.
        holder.bindTo(concert)
    }

    companion object {
        private val DIFF_CALLBACK = ... // See Implement the diffing callback section.
    }
}

Java

public class ConcertAdapter
        extends PagedListAdapter<Concert, ConcertViewHolder> {
    protected ConcertAdapter() {
        super(DIFF_CALLBACK);
    }

    @Override
    public void onBindViewHolder(@NonNull ConcertViewHolder holder,
            int position) {
        Concert concert = getItem(position);

        // Note that "concert" can be null if it's a placeholder.
        holder.bindTo(concert);
    }

    private static DiffUtil.ItemCallback<Concert> DIFF_CALLBACK
            = ... // See Implement the diffing callback section.
}

Le PagedListAdapter gère les événements de chargement de page à l'aide d'un objet PagedList.Callback. Lorsque l'utilisateur fait défiler la page, PagedListAdapter appelle PagedList.loadAround() pour fournir des indications au PagedList sous-jacent pour savoir quels éléments il doit récupérer à partir de DataSource.

Intégrer le rappel de vérification différentielle ("diffing")

L'exemple suivant montre une intégration manuelle de areContentsTheSame(), qui compare les champs d'objet pertinents :

Kotlin

private val DIFF_CALLBACK = object : DiffUtil.ItemCallback<Concert>() {
    // The ID property identifies when items are the same.
    override fun areItemsTheSame(oldItem: Concert, newItem: Concert) =
            oldItem.id == newItem.id

    // If you use the "==" operator, make sure that the object implements
    // .equals(). Alternatively, write custom data comparison logic here.
    override fun areContentsTheSame(
            oldItem: Concert, newItem: Concert) = oldItem == newItem
}

Java

private static DiffUtil.ItemCallback<Concert> DIFF_CALLBACK =
        new DiffUtil.ItemCallback<Concert>() {

    @Override
    public boolean areItemsTheSame(Concert oldItem, Concert newItem) {
        // The ID property identifies when items are the same.
        return oldItem.getId() == newItem.getId();
    }

    @Override
    public boolean areContentsTheSame(Concert oldItem, Concert newItem) {
        // Don't use the "==" operator here. Either implement and use .equals(),
        // or write custom data comparison logic here.
        return oldItem.equals(newItem);
    }
};

Étant donné que votre adaptateur inclut la définition de comparaison d'éléments, il détecte automatiquement les modifications apportées à ces éléments lorsqu'un nouvel objet PagedList est chargé. L'adaptateur déclenche donc des animations d'éléments efficaces dans votre objet RecyclerView.

Diffing à l'aide d'un autre type d'adaptateur

Si vous choisissez de ne pas hériter de PagedListAdapter, par exemple si vous utilisez une bibliothèque fournissant son propre adaptateur, vous pouvez toujours utiliser la fonction de diffing de l'adaptateur de la bibliothèque Paging en travaillant directement avec un objet AsyncPagedListDiffer.

Fournir des espaces réservés dans votre UI

Si vous souhaitez que votre interface utilisateur affiche une liste avant que votre application n'ait fini d'extraire les données, vous pouvez présenter des éléments de liste d'espace réservé à vos utilisateurs. PagedList gère ce cas de figure en marquant les données de l'élément de liste comme null jusqu'à ce qu'elles soient chargées.

Les espaces réservés offrent les avantages suivants :

  • Compatibilité avec les barres de défilement : la PagedList fournit le nombre d'éléments de liste au PagedListAdapter. Ces informations permettent à l'adaptateur de tracer une barre de défilement qui représente toute la taille de la liste. Lorsque de nouvelles pages se chargent, la barre de défilement ne saute pas, car la taille de votre liste ne change pas.
  • Aucune icône de chargement requise : la taille de la liste étant déjà connue, il est inutile d'alerter les utilisateurs lorsque d'autres éléments sont en cours de chargement. Les espaces réservés eux-mêmes transmettent cette information.

Avant d'ajouter la prise en charge des espaces réservés, tenez compte des conditions préalables suivantes :

  • Requiert un ensemble de données dénombrables : les instances de DataSource de la bibliothèque de persistance Room peuvent compter leurs articles de manière efficace. Toutefois, si vous utilisez une solution de stockage local personnalisée ou une architecture de données basée uniquement sur le réseau, il peut se révéler coûteux, voire impossible, de déterminer le nombre d'éléments qui composent votre ensemble de données.
  • L'adaptateur doit tenir compte des éléments non chargés : l'adaptateur ou le mécanisme de présentation que vous utilisez pour préparer la liste en cas d'augmentation doit gérer les éléments de liste vides. Par exemple, lorsque vous liez des données à un ViewHolder, vous devez fournir des valeurs par défaut pour représenter les données non chargées.
  • Requiert des vues d'élément de taille identique : si la taille des éléments de la liste peut changer en fonction de leur contenu, comme les mises à jour des réseaux sociaux, le balayage croisé d'éléments n'est pas optimal. Nous vous recommandons alors vivement de désactiver les espaces réservés.

Envoyer un commentaire

Faites-nous part de vos commentaires et de vos idées via les ressources suivantes :

Issue Tracker
Signalez les problèmes pour que nous puissions corriger les bugs.

Ressources supplémentaires

Pour en savoir plus sur la bibliothèque Paging, consultez les ressources suivantes.

Exemples

Ateliers de programmation

Vidéos