Passion Flutter : Top 10 des librairies pour vos applications (Edition 2021)

A La Mobilery, ça fait maintenant quelques années (2~3) que nous nous sommes mis à Flutter !

Si vous avez cliqué sur cet article, vous connaissez probablement Flutter, donc vous pouvez passer directement au top 10.
Sinon, un bref résumé de quelques lignes ne fera pas de mal. Flutter est un framework édité par Google basé sur dart pour faire du développement cross platform.
Cela veut dire que vous écrivez le code une seule fois, et que l’application générée peut être utilisée (dans notre cas) sur iOS et Android (et même en Web & Windows / macOS / linux).

Pour être franc, on y a cru assez rapidement, mais comme chaque techno émergente, il fallait trouver des clients pour nous suivre.
A ce moment, le roi du cross platform, c’était React Native, le framework de Facebook tout aussi puissant mais avec une approche différente, basé sur du web et un bridge JS.

Finalement, nous avons réussi à convaincre et certains clients nous ont suivi, comme EBP, le groupe ADEO et de nombreux autres maintenant!
Aujourd’hui nous travaillons à une deuxième application pour EBP et une autre pour un groupe de crèche dont on parlera probablement plus tard !

Comme n’importe quel framework, Flutter (qui pour rappel se base sur dart) dispose d’une communauté et de plugins et librairies développés en open-source pour vous aider à booster le développement de vos applications.

Ces librairies sont référencées sur pub.dev ou directement sur un hosting git (comme github, par exemple).

🤯 Pourquoi utiliser une librairie tierce ?

Dans le développement logiciel, chaque client est unique, chaque demande est unique, chaque application est unique, chaque développement est unique.

C’est d’ailleurs ce qui rend les estimations fiables impossibles. (J’insiste sur le fiable, on sait donner une fourchette avec un taux de confiance, mais donner un chiffre exact sans se tromper relève de l’absurde, il y a même une loi qui en parle).

Quand bien même, cela ne veut pas dire qu’on repart d’une page totalement vierge chaque fois. Dans les applications, on a souvent des besoins primaires qui vont se ressembler. Quelques exemples

  • Afficher une image (locale ou venant d’internet)
  • Récupérer une donnée venant d’une API
  • Sauvegarder quelque chose sur le téléphone
  • Afficher une date de manière claire (par exemple 31/12/2021 ou alors le Vendredi 31 Décembre 2021)
  • Et bien d’autres

Toutes ces actions sont assez communes, et il n’aurait aucun sens de re-développer ce comportement à chaque fois qu’on crée une nouvelle application.
C’est là où les librairies et plugins entrent en jeu. Ils font ce boulot pour nous.

Maintenant que les bases sont posées, voyons notre Top 10 de l’année 2021 !

🔝 Notre Top 10

Sans plus attendre, voici notre top 10 :

  1. 🥇 FlutterFire
  2. 🥈 freezed
  3. 🥉 flutter_svg
  4. 4️⃣ cached_network_image
  5. 5️⃣ provider
  6. 6️⃣ jiffy
  7. 7️⃣ dio
  8. 8️⃣ auto_size_text
  9. 9️⃣ path_provider
  10. 🔟 surprise !

🥇 Top 1 : FlutterFire

Bon OK, on triche un peu avec celle-là, FlutterFire c’est un groupe d’une 15aine de librairies !

L’idée derrière FlutterFire c’est de simplifier les interactions entre vos applications Flutter et Firebase.
Firebase, c’est l’outil de Google pour accélérer le développement web et mobile !

Derrière cette librairie compatible web et mobile, se cache des fonctionnalités bluffantes

  • Authentification des utilisateurs
  • Accès aux firestore (base de donnée NoSQL)
  • Accès au storage (sauvegarde de documents & fichiers)
  • Gestion des push notifications
  • Publicité InApp
  • Remontée automatique des crash et logs
  • Et j’en passe.

Bref, grâce à FlutterFire, vous pouvez très facilement en quelques lignes de code connecter votre application à un projet Firebase et ça, c’est vraiment top.

🥈 Top 2 : Freezed

Freezed est un package plutôt cool.
Dans la catégorie “éviter d’écrire du code sans saveur”, Freezed gagne une médaille.

En effet, ce package permet, grâce à quelques annotations, de générer automatiquement des data class.

Kézaco ? En gros, vos réponses API et vos modèles. Freezed s’occupe de tout, du equals aux membres privés en passant par le parsing json (il s’appuie sur json_serializable pour ça). Bref, un must have

Par exemple, une classe simple d’un utilisateur sera définie comme tel dans un fichier user.dart

part 'user.freezed.dart';
part 'user.g.dart';

@freezed
class User with _$User {
  const factory User({
    required String id,
    required String lastName,
    required String firstName,
    required String email,
    required String? phoneNumber
    required bool isActive
 }) = _User;

  factory User.fromJson(Map<String, dynamic> json) =>
      _$UserFromJson(json);
}

Derrière, Freezed (en s’aidant de json_serializable) va générer les fichiers user.freezed.dart et user.g.dart qui vont nous éviter d’écrire tout le boilerplate de base (equals, toJson, fromJson, hashCode, constructeurs, copy, etc).

🥉 Top 3 : flutter_svg

Ha le SVG ! Depuis qu’il est là, on ne jure que par lui.

Pour intégrer des icônes, avant on avait les formats classiques (png, jpg), le problème c’est qu’avec toutes les résolutions d’écrans, on a 2 side effects

  • Soit on doit embarquer des images énormes et du coup, exploser la taille de nos applications
  • Soit gérer chaque taille d’écran et avoir beaucoup de gestion sans valeur utilisateur
  • Soit avoir des applications moches (pas besoin d’être designer pour dire qu’une icône pixellisée dans un menu, c’est juste moche)

Le SVG corrige ce problème parce que les images sont décrites vectoriellement. Dit de manière simple, on peut zoomer et dézoomer à l’infini sans perte de qualité.

Alors je dis icônes, car pour les images c’est pas vraiment fait pour.

Le problème, c’est qu’il n’y a rien de natif sur Flutter pour intégrer ça. Heureusement, flutter_svg est là pour ça. Très simplement on met l’image au format svg dans nos assets et il ne reste plus qu’à

final Widget svgIcon = SvgPicture.asset(
  assetName,
  semanticsLabel: 'Accessibility Rocks'
)

Fini de devoir embarquer 200Mo d’icônes full hd ! Vive le svg.

4️⃣ Top 4 : cached_network_image

Dans une application, qu’elle soit web ou mobile, on voit de plus en plus d’images.

Deux options, soit elles sont embarquées en local et tant mieux, soit elles viennent d’internet et de vos API.

Quand ces images sont affichées 1 ou 2 fois, tout se passe bien, pas de souci, mais quand la même image est affichée chaque fois que l’application se lance ou régulièrement, s’il faut la télécharger à chaque fois, ça commence à coûter cher (en énergie et en données mobiles).

Alors faites un geste pour la planète et pour vos utilisateurs, utilisez cached_network_image

cached_network_image va s’occuper de garder les images que vous afficher en cache et de ne pas les retélécharger chaque fois ! En plus de faire des économies, vous augmentez la rapidité et la fluidité de votre application.

Que demander de plus ? Il y a même des options pour spécifier quoi afficher en attendant le téléchargement complet ou ce qu’il faut montrer en cas d’erreur.

CachedNetworkImage(
  imageUrl: "http://via.placeholder.com/350x150",
  placeholder: (context, url) => Image.asset('assets/loading.png')
  errorWidget: (context, url, error) => Icon(Icons.error)
)

5️⃣ Top 5 : provider

Ha provider… Comment expliquer simplement un outil comme celui-là ?!

provider est une librairie pour aider le state management, c’est-à-dire créer et mettre à jour vos écrans en fonction de certaines actions (utilisateurs, ou api).

Par exemple

  • Mettre à jour un écran quand une API a renvoyé une réponse
  • Filtrer une liste en fonction de filtres utilisateurs
  • Mettre à jour l’application quand on change de profil (par exemple Netflix a un compte et plusieurs profils)
  • Et bien d’autres

Pour faire sa magie, provider se base sur InheritedWidget.

Cela va forcément être réducteur de mettre un exemple de code ici tellement provider permet des choses. Mais en gros, vous déclarez une liste d’éléments qui seront accessibles à vos widgets en wrappant votre application.

runApp(
 MultiProvider(
    providers: [
      Provider<SomeClass>(create: (_) => SomeClass()),
      Provider<SomeAPI>(create: (_) => SomeAPI()),
      Provider<SomeDatabase>(create: (_) => SomeDatabase()),

      Provider<AppRepository>(create: (ctx) => AppRepository(
        api: ctx.read<SomeAPI>(),
        database: ctx.read<SomeDatabase>()
      )),
    ],
    child: MyApp()
  )
)

Et ainsi dans vos widgets vous pourrez accéder à vos classes simplement en utilisant le BuildContext

/// Soit si vous voulez écouter des changements grâce aux ChangeNotifier 
/// et Flutter va reconstruire votre Widget chaque fois que cette donnée change 
/// sans rien vous demander
@override
Widget build(BuildContext context) {
  context.watch<SomeNotifier>().someObservableData;
}


/// Soit vous voulez déclencher une action sans forcément écouter de retour 
/// ou s'abonner aux changements
Provider.of<SomeNotifier>(context, listen: false).updateDataWithParameters(someParams);

5️⃣ Top 6 : jiffy

jiffy est un indispensable quand on commence à manipuler des dates.

Ce qu’on fait constamment !

Formater une date pour la montrer à l’utilisateur, calculer des différences ou ajouter des durées, quel enfer 🔥.

Heureusement jiffy est là ! Inspiré du fonctionnement de la très populaire librairie momentjs (qui est restée au top pendant des années) jiffy simplifie très fortement la manipulation de ces dates.

Elle va plus loin qu’intl sur les dates et donc est très pratique, quelques exemples:

/// Le 31 décembre 2021 à 23:59
Jiffy([2021, 12, 31, 23, 59]).format("[Le] dd MMMM yyyy [à] hh:mm"); 

/// Si on lance ça le 29 décembre
Jiffy([2021, 12, 31]).fromNow() // in 2 days 

/// Et pour finir la manipulation de dates le 01/01/2022
Jiffy([2021, 12, 31]).add(duration: Duration(days: 1))

7️⃣ Top 7 : dio

Dio est un package plutôt populaire sur flutter car il simplifie les appels HTTP (comprendre la consommation d’API)

Faire des appels http n’est déjà pas très compliqué avec flutter, c’est vrai, mais alors pourquoi s’encombrer d’une librairies en plus ?

En quelques mots

  • Les intercepteurs (par exemple pour logger ou rafraîchir un token)
  • Les FormData
  • Annuler une requête
  • télécharger des fichiers
  • mettre un timeout facilement

Tout cela est rendu extrêmement simple par dio, là où faire tout cela avec http est plutôt resté simple (dans le sens KISS).

Autre avantage de dio, la librairie retrofit, qui permet de décrire des API avec des annotations

Bref, pas forcément un must have, mais un bon accélérateur.

/// Simple get
response = await Dio().get('http://www.google.com')

/// Simple post
response = await dio.post('/post_data', data: {'id': 42, 'name': 'aloha'});

/// Upload de fichier avec suivi de progression
await dio.post(
  '/post_file',
  data: MyFileAsBytes,
  onSendProgress: (int sent, int total) {
    print('Progression = $sent/$total');
  },
)

/// Etc

Et du coup, je ne résiste pas à l’envie de vous mettre un petit exemple de retrofit

@RestApi(baseUrl: "https://my.api.fr/api/v1/")
abstract class SomeAPI {
  factory SomeAPI(Dio dio, {String baseUrl}) = _SomeAPI;

  @GET("/users")
  Future<List<Users>> getUsers();
}

Et voilà, on a notre API qui va chercher nos utilisateurs sur https://my.api.fr/api/v1/users, Users qui sont parsés grâce à freezed si vous avez suivi.

8️⃣ Top 8 : auto_size_text

Je ne vais pas vous mentir, le top 8 a été compliqué à statuer !

Mais dans toutes nos applications (ou presque) on se sert d’auto_size_text.

La problématique: vous avez un écran avec une taille limitée, et vous voulez afficher un texte dedans
Les solutions : couper le texte qui dépasse, limiter le nombre de caractères en entrée, ou resizer le texte au fur et à mesure.

auto_size_text opte pour la 3ème option, et bizarrement c’est celle que préfèrent nos clients en général.

Démonstration d’AutoSizeText dispo sur leur site

Grâce à auto_size_text, plus besoin de contraindre vos utilisateurs trop fortement et vos designers ne vont plus devenir fous !

AutoSizeText(
  'The text to display',
  style: TextStyle(fontSize: 20),
  maxLines: 2,
)

9️⃣ Top 9 : path_provider

Encore un package of the week dans notre Top 10 !

path_provider fait partie de ces libraires si simples et si indispensables.

Pour résumer, elle permet d’accéder aux dossiers spécifiques que le système (iOS ou Android, Linux, macOS ou Windows) a réservé pour notre application.

C’est important car il n’y a que dans ces dossiers qu’on peut faire globalement ce qu’on veut.

Par ce qu’on veut, ça ne veut pas dire la foire, mais plutôt des choses comme:

  • sauvegarder des fichiers de manière temporaire ou non
  • sauvegarder d’autres documents
  • enregistrer des choses dans “téléchargements”
  • etc

Notre top 3 des dossiers désormais très simple d’accès :

/// Dossier de fichiers temporaires
Directory tempDir = await getTemporaryDirectory();

/// Dossier de documents de l'app
Directory appDocDir = await getApplicationDocumentsDirectory();

/// Dossier de téléchargements
Directory downloadsDir = await getDownloadsDirectory();

🔟 Top 10 : La vôtre

Surprise ! Bon le Top 10 est volontairement provocateur.

Quand on dit la vôtre, on ne parle pas forcément de publier une librairie et de la rendre accessible. Mais si vous avez des bouts de code que vous utilisez souvent, faites-vous un dépôt git, un package flutter et mettez les dessus !

Le système pubspec est plutôt cool à ce sujet et importer un package depuis git est une chose plutôt facile, il vous suffit de spécifier que le package vient de git et tout fonctionnera parfaitement bien

dependencies:  
  our_awesome_lib:
    git:
     url: git@somegitrepository
     version: 1.0.0

Et si jamais vous pouvez même faire du multi dossier (à éviter si on est plusieurs sur le projet ou alors en monorepo)

dependencies:  
  our_awesome_lib:
    path: /some/path/with/our/lib

⚠️ Attention cela dit

Un feu de palette
Votre app si vous abusez des librairies n’importe comment

Attention cela dit à ne pas en abuser, une librairies c’est aussi du code sur lequel on n’a aucun contrôle. Cela peut s’avérer un danger si une partie critique de notre application repose trop dessus.

En plus de l’aspect sécurité, vous n’avez pas le contrôle sur la maintenance d’une librairie, donc attention à celles que vous utilisez. On a vite fait de se retrouver avec un package plus mis à jour depuis plusieurs mois qui fait planter notre application.

Pour autant, il serait dommage de se passer de ces briques de code qui simplifient la vie.

Comme n’importe quoi d’autre c’est une question de curseur donc 🙂

De plus, faites bien attention aux licenses de vos librairies, nombre d’entre elles demandent à être créditées (prévoir donc un AboutDialog quelque part et laisser flutter faire le reste)

Créditer les librairies grâce à l’AboutDialog

📱 Le mot de la fin

En cette fin d’année 2021, nous espérons que cet article vous a plu ! Vous avez peut-être découvert des choses ou bien vous êtes reconnus dans ce qu’on utilise.

Pour commencer 2022 au top, je ne peux vous laisser partir sans vous dire 2 choses

SI jamais vous avez des idées, des envies, des besoins, en applications web et/ou mobile, nos équipes sont là pour vous accompagner et construire avec vous ces produits, alors n’hésitez pas à nous contacter, soit sur la page de contact, soit directement par email sur contact@lamobilery.fr !

Enfin, si jamais tu es dév et que tu cherches un nouveau challenge pour cette année, n’hésite pas à aller jeter un oeil sur notre page welcome to the jungle ou encore welovedevs.

Et si jamais vous avez envie de papoter de tout ça, n’hésitez pas à me contacter sur qklein@lamobilery.fr pour continuer à en parler 🙂

A bientôt !

Quentin Klein

Tech Leader de l'agence de Paris
29 décembre 2021

Quentin et le Lead Tech de l'agence de Paris. Accroc au développement mobile, il est particulièrement intéressé par Android et Flutter.