Lazy Loading dans le développement mobile — fonctionnement, principes et implémentation

Auteur : IT Sectr Publié le : 2026-04-01 Temps de lecture : 9 min

Le Lazy Loading est une stratégie de chargement différé des données, images et composants, dans laquelle les ressources ne sont pas demandées au démarrage de l'application, mais au moment où l'utilisateur en a réellement besoin. Selon le Guide Android Paging 3, le chargement différé des listes réduit la consommation mémoire de 60–80% lors du traitement de grands ensembles de données. L'initialisation différée est le principe clé qui sous-tend toutes les implémentations de Lazy Loading.

Points clés

  • Lazy Loading est un modèle de chargement différé qui économise la mémoire et accélère le premier lancement
  • LazyVStack et LazyHStack sont des composants intégrés SwiftUI pour les listes différées
  • Paging 3 est une bibliothèque Android pour le chargement paginé des données depuis l'API et la base de données
  • Les bibliothèques d'images (Glide, Coil, Kingfisher) chargent les images uniquement lorsqu'elles apparaissent à l'écran
  • Le préchargement est un chargement anticipé, le revers du Lazy Loading pour une UX fluide

Qu'est-ce que le Lazy Loading

Le Lazy Loading (chargement différé ou paresseux) est un modèle de conception et d'optimisation dans lequel les ressources de l'application ne sont pas chargées au démarrage, mais immédiatement avant leur utilisation. Dans le développement mobile, le Lazy Loading s'applique à trois catégories principales : les données (pagination des listes), les images (chargement au défilement) et les composants (piles et vues différées).

L'opposé du Lazy Loading est l'Eager Loading (chargement immédiat), où toutes les ressources sont chargées au démarrage de l'écran. L'Eager Loading est plus simple à implémenter mais consomme plus de mémoire et augmente le temps d'affichage initial. Pour les listes contenant des milliers d'éléments, l'Eager Loading provoque des OOM (Out of Memory) sur les appareils à mémoire limitée. Le Lazy Loading résout ce problème en chargeant uniquement ce qui est visible à l'écran et en chargeant le reste au fur et à mesure que l'utilisateur défile.

Dans le contexte d'iOS et Android, le Lazy Loading est implémenté à différents niveaux. SwiftUI fournit LazyVStack et LazyHStack pour le rendu différé. UIKit utilise UITableView avec dequeueReusableCell. Android utilise RecyclerView avec un pool de ViewHolder. Au niveau des données, Room avec Paging 3 et Core Data avec NSFetchedResultsController. Le choix de la technologie spécifique dépend de la pile et des exigences de performance.

Principes de fonctionnement du chargement différé

Le principe central du Lazy Loading est de charger exactement la quantité de données nécessaire pour l'état actuel de l'écran, plus un tampon anticipé pour un défilement fluide. Cette approche repose sur deux mécanismes : le suivi de visibilité et la virtualisation des éléments.

Suivi de visibilité

Le mécanisme de suivi détermine quels éléments se trouvent dans la zone visible de l'écran (viewport). Sous Android, ce sont LinearLayoutManager ou GridLayoutManager qui le font via les méthodes findFirstVisibleItemPosition et findLastVisibleItemPosition. Sous iOS, UIScrollView fournit bounds.origin.y et contentOffset.height pour calculer la zone visible. Lorsqu'un élément entre dans le viewport (ou le tampon de préchargement), son chargement est déclenché. Lorsqu'un élément quitte l'écran, ses ressources peuvent être libérées ou déplacées vers le cache.

kotlin
// Android — suivi de visibilité dans RecyclerView
recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
    override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
        val layoutManager = recyclerView.layoutManager as LinearLayoutManager
        val lastVisible = layoutManager.findLastVisibleItemPosition()
        val totalCount = layoutManager.itemCount
        // Chargement de la page suivante s'il en reste < 5 éléments
        if (lastVisible >= totalCount - 5) {
            loadMoreItems()
        }
    }
})

Mise en tampon et préchargement

Le tampon de préchargement est le chargement anticipé des éléments qui apparaîtront bientôt à l'écran. RecyclerView prend en charge GapWorker.Prefetch via layoutManager.setItemPrefetchEnabled(true). iOS UITableView prend en charge le préchargement via UITableViewDataSourcePrefetching. La taille du tampon de préchargement est généralement de 1 à 2 écrans d'avance, offrant un compromis entre la fluidité du défilement et la consommation mémoire. Un tampon de préchargement trop grand annule les avantages du Lazy Loading ; un trop petit crée des espaces vides lors d'un défilement rapide.

Lazy Loading des images

Les images sont le type de ressource le plus lourd dans les applications mobiles. Une seule photo de 12 MP peut occuper 3 à 5 MB sous forme non compressée. Le Lazy Loading des images empêche le chargement de centaines d'images invisibles en mémoire, ce qui serait fatal pour les listes avec des avatars d'utilisateurs ou des catalogues de produits.

Bibliothèques pour Android : Glide et Coil

Glide est la bibliothèque de chargement d'images la plus populaire pour Android, avec prise en charge du cache, des transformations et des animations. Coil est une alternative plus légère, écrite en Kotlin avec des coroutines. Les deux bibliothèques suspendent automatiquement le chargement lorsqu'une ImageView quitte l'écran et annulent les requêtes lors de la réutilisation d'un ViewHolder. Coil utilise des coroutines et pèse ~1,5 Mo contre ~4 Mo pour Glide, ce qui le rend préférable pour les projets axés sur la taille de l'APK.

kotlin
// Coil — chargement différé d'images
imageView.load("https://example.com/image.jpg") {
    crossfade(true)
    placeholder(R.drawable.placeholder)
    size(512, 512)
    memoryCachePolicy(CachePolicy.ENABLED)
}

Bibliothèques pour iOS : Kingfisher et SDWebImage

Kingfisher est une bibliothèque pour iOS avec prise en charge de Swift Concurrency, du cache disque et mémoire, et du préchargement pour UICollectionView. SDWebImage est une bibliothèque plus ancienne avec des racines Objective-C mais avec prise en charge de Swift. Les deux bibliothèques s'intègrent à UIImageView et gèrent automatiquement le cycle de vie du chargement : elles annulent les requêtes lors de la réutilisation d'une cellule, chargent les images uniquement lorsque la cellule est visible et libèrent la mémoire lors d'un avertissement de mémoire insuffisante.

Lazy Loading des données et listes

Les grandes listes de données sont le principal domaine d'application du Lazy Loading dans les applications mobiles. Fil d'actualité, catalogue de produits, chats, historique des transactions — tout écran avec une liste potentiellement infinie nécessite une pagination et un chargement différé.

Paging 3 pour Android

Paging 3 est une bibliothèque d'Android Jetpack qui implémente le cycle complet de chargement différé : demande de données à RemoteMediator (API + base de données), mise en cache dans Room, sortie page par page via PagingData et affichage via AsyncPagingDataAdapter. Paging 3 prend en charge trois types de pagination : basée sur les pages, basée sur les éléments (offset/limit) et basée sur les clés (clés de pagination de l'API). Separator est la prise en charge intégrée des séparateurs entre les pages pour les indicateurs de chargement.

kotlin
// Paging 3 — chargement différé depuis l'API
class ArticlePagingSource(
    private val api: ArticleApi
) : PagingSource<Int, Article>() {

    override suspend fun load(
        params: LoadParams<Int>
    ): LoadResult<Int, Article> {
        return try {
            val page = params.key ?: 1
            val response = api.getArticles(page)
            LoadResult.Page(
                data = response.items,
                prevKey = page.takeIf { it > 1 }?.dec(),
                nextKey = page + 1
            )
        } catch (e: Exception) {
            LoadResult.Error(e)
        }
    }
}

SwiftUI LazyVStack et LazyHStack

LazyVStack est un conteneur intégré SwiftUI qui crée et rend les éléments uniquement lorsqu'ils apparaissent à l'écran. Contrairement à VStack, qui calcule immédiatement la disposition de tous les éléments enfants, LazyVStack reporte la création de la vue jusqu'à ce que l'élément devienne visible ou entre dans la plage de préchargement. LazyHStack est l'équivalent horizontal pour les carrousels. Pour les grandes listes, Apple recommande d'utiliser List, qui fonctionne en interne comme LazyVStack avec un recyclage intégré supplémentaire.

swift
// SwiftUI — LazyVStack avec chargement différé
ScrollView {
    LazyVStack(spacing: 8) {
        ForEach(articles) { article in
            ArticleRow(article: article)
                .onAppear {
                    if article == articles.last {
                        viewModel.loadMore()
                    }
                }
        }
    }
}

Lazy Loading des composants d'interface

Le chargement différé des composants d'interface est une technique où des parties de l'interface (en-têtes, pieds de page, sections de paramètres, onglets) ne sont pas créées au démarrage de l'écran, mais au premier accès. Cela accélère le rendu initial et réduit la charge sur le thread principal.

Android : ViewStub et chargement différé des Fragments

ViewStub est un espace réservé de View léger sous Android qui ne prend pas de place dans la mise en page et ne crée pas de Views enfants avant l'appel de inflate(). Idéal pour les sections rarement utilisées : panneau de recherche, paramètres avancés, blocs publicitaires. Le chargement différé des Fragments est une technique où Fragment.onCreateView est reporté jusqu'à ce que l'utilisateur bascule sur cet onglet. Il est implémenté via isVisible ou UserVisibleHint dans ViewPager.

AndroidX fournit SplitInstallManager pour le chargement différé des modules à la demande. Les modules de configuration, de diagnostic ou de fonctionnalités supplémentaires sont chargés en tant que modules Dynamic Feature uniquement à la première demande de l'utilisateur. Cela réduit la taille de base de l'application de 30 à 50 % et implémente simultanément le principe du Lazy Loading non seulement au niveau des données, mais aussi au niveau du code.

iOS : TabView et la nature paresseuse de ViewBuilder

TabView dans SwiftUI charge le contenu de chaque onglet de manière différée — uniquement lorsque l'onglet est activé. UIKit UITabBarController crée tous les contrôleurs enfants au démarrage par défaut, mais ce comportement peut être modifié en ne les ajoutant pas immédiatement à tabBarController.viewControllers et en les substituant au fur et à mesure que l'utilisateur change d'onglet. UIStackView avec des arrangedSubviews ajoutés dynamiquement suit également le principe du Lazy Loading — n'ajoutez une Subview que lorsque l'utilisateur effectue une action nécessitant cette partie de l'interface.

Pour optimiser le chargement global de l'écran, combinez le Lazy Loading à tous les niveaux : ViewStub pour les sections rarement utilisées, Paging 3 pour les données, Glide/Coil pour les images et l'initialisation différée de ViewModel via Hilt/Dagger Scopes ou Swinject. Cette approche produit un écran qui se charge en 200 à 400 ms même sur des appareils économiques avec 3 Go de RAM.

Questions fréquentes

Quand ne pas utiliser le Lazy Loading ?

Si l'écran affiche de manière garantie peu d'éléments (jusqu'à 20) et que tous sont nécessaires immédiatement, le Lazy Loading est excessif. Pour les listes rarement défilées, l'Eager Loading peut être plus simple et plus rapide à implémenter sans perte de performance notable.

Comment le Lazy Loading affecte-t-il la mémoire ?

Il réduit la consommation mémoire maximale de 3 à 10 fois pour les grandes listes, car seuls les éléments visibles plus le tampon de préchargement sont stockés en mémoire. Cependant, l'ajout du préchargement et de la mise en cache des images crée une consommation mémoire modérée qui doit être gérée.

Que choisir — LazyVStack ou List dans SwiftUI ?

List est préférable pour les données homogènes avec prise en charge du balayage, du glisser-déposer et de la sélection intégrée. LazyVStack est pour les mises en page personnalisées avec différents types de cellules, sections et espacements non standard. List fonctionne en interne comme LazyVStack avec des fonctionnalités supplémentaires.

Comment déboguer les problèmes de chargement différé ?

Sous Android, utilisez l'Inspecteur de mise en page pour voir la hiérarchie des vues : avec Lazy Loading, la plupart des éléments doivent être absents de l'arbre. Sous iOS, utilisez Xcode Debug View Hierarchy. Si tous les éléments sont présents lors du défilement, le Lazy Loading ne fonctionne pas.

Qu'est-ce qui est le plus important — la vitesse de chargement ou l'économie de mémoire ?

Les deux paramètres sont importants, mais la priorité dépend de la plateforme. Sur iOS avec ARC et une gestion efficace de la mémoire, la priorité est la vitesse de chargement. Sur Android avec JVM et GC, la priorité est l'économie de mémoire, car chaque allocation sur le thread principal peut provoquer un gel du GC.

Résumé

  • Lazy Loading est un modèle de chargement différé qui accélère le premier lancement et économise la mémoire
  • Les images sont chargées via Glide, Coil, Kingfisher uniquement lors de l'entrée dans le viewport
  • Paging 3 pour Android fournit un chargement paginé des données avec mise en cache dans Room
  • LazyVStack dans SwiftUI reporte le rendu des éléments jusqu'à leur apparition à l'écran
  • ViewStub dans Android — chargement différé des composants d'interface au premier accès
  • Tampon de préchargement — chargement anticipé pour un défilement fluide
  • Combinez le Lazy Loading à tous les niveaux : données + images + UI

Nous développerons une application mobile clé en main

IT Sectr crée des applications iOS et Android pour les startups et les entreprises depuis 2017. Nous vous conseillerons et vous proposerons la meilleure solution.

Discuter du projet

Lisez aussi