đŸ’Ÿ 2.4 Persistance et scĂ©narios offline

Module 335 – RĂ©aliser une application pour mobile

🎯 Objectif d'apprentissage

À la fin de ce chapitre, vous serez capables de :

  • Comprendre les diffĂ©rentes formes de persistance locale sur mobile
  • Distinguer bases de donnĂ©es locales, stockage clé–valeur et stockage de fichiers
  • Expliquer le fonctionnement des scĂ©narios offline et du cache local
  • GĂ©rer les erreurs rĂ©seau, la synchronisation et la rĂ©silience d'une application

đŸ€” 2.4.1 Introduction : pourquoi la persistance ?

Une application mobile n’est pas toujours connectĂ©e Ă  Internet :

  • tunnels
  • bĂątiments
  • zones rurales
  • mĂ©tro
  • mode avion

Pourtant, les utilisateurs s’attendent Ă  ce qu’elle continue de fonctionner, mĂȘme hors ligne.

2.4.1 Persistance : définition

La persistance = capacitĂ© d’une application Ă  stocker des donnĂ©es localement sur l’appareil, afin qu’elles restent disponibles :

  • mĂȘme sans rĂ©seau
  • mĂȘme aprĂšs fermeture de l’app

Exemples de données persistées :

  • PrĂ©fĂ©rences utilisateur (langue, thĂšme sombre)
  • Session de connexion
  • Notes, listes, messages, documents
  • Cache de donnĂ©es venant d’une API (ex. dernier rapport mĂ©tĂ©o)

2.4.1 Trois briques principales

La gestion du mode offline repose sur 3 briques :

  1. Stockage lĂ©ger (clé–valeur)
  2. Base de données locale (SQLite, Realm, CoreData, etc.)
  3. Synchronisation entre local et serveur quand la connexion revient

2.4.1 Exemple – Application de notes

Une application de notes doit permettre :

  • d’ajouter / modifier / supprimer des notes mĂȘme hors ligne
  • puis de synchroniser ces notes avec le cloud
  • dĂšs que la connexion revient

🎯 Objectif du chapitre :
Comprendre les solutions de stockage et comment assurer le offline sans frustrer l’utilisateur.

🔐 2.4.2 Stockage clé–valeur – Principe

Le stockage clé–valeur = forme de persistance la plus simple.

On enregistre de petites infos sous forme :

clĂ© → valeur

Comme un dictionnaire.

2.4.2 Stockage clé–valeur – À quoi ça sert ?

  • PrĂ©fĂ©rences utilisateur

    • thĂšme sombre / clair
    • langue
    • notifications activĂ©es
  • Petits Ă©tats internes

    • derniĂšre page visitĂ©e
    • tutoriel dĂ©jĂ  vu
  • Tokens d’authentification

    • JWT
    • OAuth
  • ParamĂštres de configuration

⚠ Pas adaptĂ© aux donnĂ©es volumineuses (listes, historiques, gros objets
).

2.4.2 Outils selon la plateforme

Plateforme Outil Particularités
Android SharedPreferences Simple, rapide, non chiffré
iOS UserDefaults Paramùtres internes de l’app
Ionic / Capacitor Preferences API JS → natif unifiĂ©e iOS/Android
Flutter shared_preferences Stockage léger persistant

2.4.2 Exemple – Capacitor Preferences

import { Preferences } from '@capacitor/preferences';

await Preferences.set({
  key: 'theme',   
  value: 'dark', 
});

Ici, on mĂ©morise le thĂšme choisi par l’utilisateur.

2.4.2 Bonnes pratiques – Clé–valeur

  • Ne jamais stocker d’infos sensibles en clair (mots de passe, donnĂ©es perso dĂ©taillĂ©es
)
  • Limiter Ă  quelques kilo-octets
  • RĂ©server ce stockage Ă  des paramĂštres ou Ă©tats simples

📂 2.4.3 Bases de donnĂ©es locales – Principe

Pour des données plus volumineuses ou structurées, on utilise une base de données locale.

Elle permet :

  • recherches (requĂȘtes)
  • tris
  • relations entre donnĂ©es
  • mises Ă  jour complexes

2.4.3 Pourquoi une base locale ?

Utile pour :

  • conserver une liste de donnĂ©es :
    • notes, produits, messages, utilisateurs, etc.
  • permettre Ă  l’app de fonctionner 100 % offline
  • crĂ©er un cache local d’API :
    • charger les donnĂ©es une fois,
    • les relire mĂȘme sans rĂ©seau

2.4.3 Solutions principales

Plateforme Solution Description
Android Room (sur SQLite) ORM moderne, facile depuis Kotlin
iOS CoreData Base orientée objets intégrée
Flutter sqflite, hive SQLite ou base clé–valeur rapide
Ionic / Capacitor @capacitor-community/sqlite Plugin SQLite natif

2.4.3 Exemples d’usage – BDD locale

  • App de recettes qui garde toutes les recettes consultĂ©es
  • App de notes avec centaines d’entrĂ©es locales
  • App de films qui garde les favoris hors ligne

2.4.3 SchĂ©ma logique – BDD locale

[ UI ] ⇄ [ ViewModel / Service ] ⇄ [ SQLite / CoreData ]

🎯 IdĂ©e : la vue ne parle jamais directement Ă  la base.
Elle passe par une couche intermédiaire (service / ViewModel).

📇 2.4.4 Stockage de fichiers – Quand et pourquoi ?

Certaines apps doivent stocker des fichiers :

  • photos
  • PDF
  • documents scannĂ©s
  • enregistrements audio
  • fichiers tĂ©lĂ©chargĂ©s

Ici, ce ne sont plus des “lignes de BDD”, mais des fichiers sur le stockage.

2.4.4 Types de fichiers courants

  • Photos prises par l’utilisateur
  • Documents scannĂ©s (factures, reçus)
  • Fichiers PDF
  • Notes vocales, enregistrements audio
  • Fichiers tĂ©lĂ©chargĂ©s depuis Internet

2.4.4 APIs selon la plateforme

Plateforme API Utilisation
Android File, MediaStore Gestion fichiers et médias
iOS FileManager Dossiers, lecture / écriture
Ionic / Capacitor Filesystem API JS → systùme de fichiers natif
Flutter file_picker, path_provider Choix de fichiers, stockage local

Exemple : une app de scan stocke les documents localement avant upload.

2.4.4 Points d’attention – Fichiers

  • GĂ©rer les permissions d’accĂšs aux fichiers / mĂ©dias
  • Faire attention Ă  la taille (photos HD = gros fichiers)
  • Nettoyer rĂ©guliĂšrement les fichiers inutilisĂ©s
    → Ă©viter de saturer le stockage

🔌 2.4.5 Cache local et usage offline – Principe

Le cache local permet d’afficher du contenu mĂȘme si :

  • le rĂ©seau est lent, ou
  • complĂštement indisponible

C’est essentiel pour :

  • Ă©viter les Ă©crans vides
  • donner une impression de rapiditĂ©

2.4.5 Pourquoi utiliser un cache ?

  • RĂ©duire les appels rĂ©seau
  • AccĂ©lĂ©rer l’affichage (donnĂ©es dĂ©jĂ  prĂ©sentes)
  • Permettre un usage offline partiel
  • AmĂ©liorer la perception de performance

Exemple : Twitter, Instagram ou YouTube affichent le dernier contenu chargé hors ligne.

2.4.5 Types de cache

  • Cache mĂ©moire (RAM)

    • trĂšs rapide
    • disparaĂźt quand l’app est fermĂ©e
  • Cache disque

    • plus lent
    • persiste entre les sessions
    • idĂ©al pour donnĂ©es d’API, images, listes

2.4.5 Stratégies de lecture des données

StratĂ©gie Description Cas d’usage
Cache-first Lire le cache, puis mettre Ă  jour en fond App mĂ©tĂ©o, liste d’articles
Network-first RĂ©seau d’abord, cache en secours Chat, donnĂ©es sensibles
Stale-while-revalidate Afficher le cache puis rafraßchir en arriÚre-plan Réseaux sociaux

2.4.5 Bonnes pratiques – Cache

đŸ§‘â€đŸ’» Conseil dĂ©veloppeur :
Toujours enregistrer un timestamp avec les données du cache.

Comme en restauration :

  • On Ă©tiquette chaque Ă©lĂ©ment du “frigo” (cache)
  • On sait quand il a Ă©tĂ© mis, et si c’est encore “frais”

đŸ”„ïž 2.4.6 Synchronisation online/offline – Principe

La synchronisation = garder la cohérence entre :

  • les donnĂ©es locales
  • les donnĂ©es serveur


 mĂȘme si l’utilisateur travaille offline.

2.4.6 Synchronisation – DĂ©fis principaux

  • Conflits entre donnĂ©es locales et distantes
  • Envoi des actions accumulĂ©es hors ligne
  • FiabilitĂ© en cas :
    • de batterie vide
    • de crash
    • de fermeture brutale de l’app

2.4.6 StratĂ©gie – File d’attente locale (queue)

Principe :

  • Chaque action utilisateur est enregistrĂ©e dans une queue :

    • “Ajouter une note”
    • “Modifier le profil”
    • “Supprimer un Ă©lĂ©ment”
  • À la reconnexion :

    • on rejoue la queue dans l’ordre
    • vers le serveur

2.4.6 StratĂ©gie – Marqueurs de version

Chaque enregistrement a un champ du type :

  • updatedAt
  • ou un numĂ©ro de version

En cas de conflit :

  • la version la plus rĂ©cente gagne
  • ou selon une rĂšgle mĂ©tier dĂ©cidĂ©e

2.4.6 StratĂ©gie – RĂ©solution des conflits

Stratégies possibles :

  • Last Writer Wins
    → la derniùre modification l’emporte

  • Serveur prioritaire
    → le serveur est l’autoritĂ© finale

  • Local prioritaire (offline-first)
    → on fait confiance à ce que l’utilisateur a saisi

Exemple : app de notes → souvent la version locale la plus rĂ©cente prime.

❌ 2.4.7 Gestion des erreurs rĂ©seau – RĂ©alitĂ© du terrain

Le réseau mobile est :

  • variable
  • parfois lent
  • parfois coupĂ©

Une bonne app anticipe :

  • les coupures
  • les ralentissements
  • les erreurs HTTP

2.4.7 Détection du statut réseau

Outils fréquents :

  • Android : ConnectivityManager
  • iOS : NWPathMonitor
  • Ionic / Capacitor : plugin Network
  • Flutter : package connectivity_plus

Permet d’afficher des messages :

  • “Vous ĂȘtes hors ligne”
  • “Connexion lente, veuillez patienter”
  • “Connexion instable – affichage du cache”

2.4.7 Stratégies de résilience

  • Retry exponentiel : 1s → 2s → 4s → 8s

  • Fallback local : cache, BDD locale
  • DĂ©sactivation de certaines actions hors ligne
  • Sauvegarde des actions dans une queue locale

Exemple :
Une app de livraison peut empĂȘcher l’envoi d’une commande hors ligne,
mais continuer d’afficher les menus via le cache.

đŸ§© 2.4.8 ActivitĂ© pratique – OĂč stocker quoi ?

(clé–valeur / base de donnĂ©es / fichiers / pas de persistance)

🎓 Objectif

Comprendre oĂč et comment stocker chaque type de donnĂ©e dans une app mobile.

2.4.8 🌇 Contexte – App CityQuest

Vous travaillez sur CityQuest, une app de chasse au trésor en ville.

Fonctionnalités :

  • QuĂȘtes gĂ©olocalisĂ©es (Ă©nigmes, points d’intĂ©rĂȘt, QR codes Ă  scanner)
  • Chaque quĂȘte rapporte des points
  • Une quĂȘte peut ĂȘtre validĂ©e avec une photo
  • L’utilisateur peut voir :
    • ses quĂȘtes en cours
    • ses quĂȘtes terminĂ©es
  • L’app doit fonctionner raisonnablement mĂȘme avec un rĂ©seau faible (cache local)

2.4.8 Ce qu’on modĂ©lise / ne modĂ©lise pas

On se concentre sur les données stockées sur le téléphone :

  • pas de schĂ©ma complet de BDD serveur
  • pas de dĂ©tails sur le profil utilisateur cĂŽtĂ© back

🎯 Objectif : apprendre à choisir le bon type de stockage local.

2.4.8 Consignes de l’exercice

Pour chaque donnée ci-dessous, indiquez dans quel type de stockage vous la placeriez :

  • Clé–valeur
  • Base de donnĂ©es locale
  • Fichiers
  • Pas besoin de persistance (si justifiĂ©)

✍ Justifiez chaque choix en 1 phrase.

2.4.8 Données à analyser (1/2)

  1. Token d’authentification (JWT, OAuth)
  2. ParamĂštre du thĂšme (sombre / clair)
  3. Choix de l’utilisateur pour tĂ©lĂ©charger les images :
    • uniquement en Wi-Fi
    • ou Wi-Fi + 5G
  4. DerniĂšre position GPS connue (pour centrer la carte au prochain lancement)
  5. Liste des quĂȘtes disponibles dans la ville
    • titre, description, coordonnĂ©es GPS, difficultĂ©, points

2.4.8 Données à analyser (2/2)

  1. État d’une quĂȘte pour l’utilisateur
    (non commencée, en cours, terminée)

  2. Historique des quĂȘtes terminĂ©es
    (dizaines ou centaines d’entrĂ©es)

  3. Cache des quĂȘtes Ă  proximitĂ© rĂ©cupĂ©rĂ©es depuis l’API
    (afficher mĂȘme si le rĂ©seau est lent)

  4. Photo de validation d’une quĂȘte prise par l’utilisateur

  5. Fichiers de logs d’erreur pour envoi ultĂ©rieur au support
    (stack traces, messages techniques)

2.4.8 Format de réponse suggéré

Donnée Type de stockage choisi Justification (1 phrase)
Token d’authentification 
 

Paramùtre du thùme 
 


 
 


💬 L’objectif est moins d’avoir “la bonne rĂ©ponse” que de savoir argumenter.

🔗 2.4.9 RĂ©fĂ©rences

đŸ’Ÿ 2.4 Persistance et scĂ©narios offline

By tirtho

đŸ’Ÿ 2.4 Persistance et scĂ©narios offline

  • 80