Utilisez-vous SaveState dans vos applications mobiles ?

Comme je l'ai expliqué dans cette présentation d'août 2020, les applications mobiles ont un cycle de vie plus perturbé que les logiciels classiques.

Sur les environnements de bureau (Windows, macOS, Linux) les programmes sont actifs (avec ou sans la focalisation) ou fermés.

Sur les environnements mobiles (iOS, Android) ils peuvent être perturbés par des éléments externes comme des notifications du système, un appel téléphonique ou d'autres activités par exemple lorsqu'on passe la main à l'application de prise de photos en cliquant sur un bouton pour revenir ensuite à l'application appelante.

A cela s'ajoute la configuration des appareils (en particulier Android) où le passage en background peut impliquer une fermeture forcée de l'application plutôt que sa mise en sommeil.

Travaillant actuellement sur une application mobile avec une cinquantaine d'écran, j'ai remis ces sujets en haut de ma pile de choses à regarder et sur lesquels travailler un peu.

Dans Delphi on peut recevoir les messages du système d'exploitation indiquant à notre application ce qui est en train de lui arriver. J'en avais parlé dans la présentation et vous avais proposé un projet de démo utilisant IFMXApplicationEventService, je ne vais pas y revenir ici.

Ce qui nous intéresse surtout c'est ce qui se produit quand une application est fermée par le système suite à une notification ou un appel alors qu'on était en train de faire quelque chose. On aimerait bien retrouver l'application en état lorsqu'elle est redémarrée.

Delphi propose deux solutions :

Pour le stockage des informations permettant de restaurer l'état de l'application, on fait ce qu'on veut. Embarcadero propose un système de flux accessible depuis la propriété SaveState de chaque fiche. J'en ai fait un exemple avec plusieurs fiches diffusé également lors de la présentation d'août 2020.

Ayant dû me poser la question d'implémenter tout ça dans Minimal FMX Project, voici où j'en suis arrivé :

  • OnSaveState est appelé lors de la fermeture des fiches, quelle que soit la raison. Si c'est lié à une action de l'utilisateur il n'est pas nécessaire d'enregistrer un contexte à reproduire lors de l'affichage suivant de la fiche.
  • Pour détecter si c'est une fermeture volontaire ou brutale, il suffit d'utiliser un booléen qu'on initialise à la création de la fiche et qu'on change dans son CloseQuery() (appelé qu'en cas de fermeture volontaire). En tester la valeur dans OnSaveState permet de savoir ce qu'on doit faire.
  • Pour déboguer le tout sous Windows, on ne peut pas utiliser la fermeture du processus depuis le gestionnaire de tâches : il n'informe pas les programmes de la demande de fermeture, il les détruit. On peut en revanche utiliser Application.Terminate.
  • La sauvegarde du contexte de chaque fiche se fait donc dans le OnSaveState. Sa restauration se fait idéalement dans OnFormCreate ou en surchargeant la méthode AfterConstruction() selon les besoins.

J'ai illustré ça avec deux exemples disponibles dans le dépôt Delphi Samples :

  • TForm_OnSaveState : pour utiliser uniquement OnSaveState de fiches, sauver le contexte du projet et le restaurer avec un stockage temporaire très simple sous forme de fichier INI.
  • SaveStateMsg : pour comprendre ce qui est appelé et dans quels cas afin de prendre en charge comme vous le voulez les OnSaveState et TSaveStateMessage.

Du côté du modèle minimal de projet FMX, c'est implémenté au niveau des ancêtres des fiches et cadres. J'ai simplement ajouté deux méthodes virtuelles LoadContext() et SaveContext() à surcharger dans vos projets. Elles sont appelées au bon moment. A vous de faire ce que vous voulez dedans.

J'ai aussi ajouté une unité facultative permettant le stockage des données liées à chaque fiche (ou à ce que vous voulez). Elle se base sur Olf.RTL.Params des librairies, comme le système de stockage par défaut des paramètres des applications dans mes starter kit pour utilitaires ou jeux vidéo et ce modèle de projet FireMonkey.

Maintenant c'est à vous de jouer si vous avez des applications mobiles développées sous forme de projets FireMonkey avec Delphi.

Mastodon