Dart d'abord, puis une méthode de gestion d'état (Riverpod ou Bloc le plus souvent), une navigation avec go_router, des appels REST ou GraphQL, Firebase pour les notifications et le suivi des crashs, et la publication sur l'App Store et Google Play : c'est ce que demandent les offres de développeur Flutter. Beaucoup associent Flutter à un back en Java, .NET, PHP ou Node.js. Une partie des missions porte sur la réécriture en Flutter d'une application native existante.
Les CV Flutter viennent en général de deux horizons. D'un côté, des développeurs Android ou Java passés à Flutter. De l'autre, des profils formés directement sur Flutter, parfois sans autre expérience mobile. Les seconds connaissent bien les widgets et calent dès qu'il faut un plugin natif, une tâche en arrière-plan ou un build iOS qui échoue. Les premiers écrivent parfois un Dart qui ressemble à du Java, avec un état mal découpé.
Demandez quelle version de Flutter tournait en production, quel package de gestion d'état a été retenu et pourquoi, quel plugin a posé problème. Le PDF regroupe 30 questions sur six axes, un cas de 20 minutes et une grille de 1 à 4.
Dart, widgets et outils autour de Flutter
Dart
Le langage de Flutter, créé par Google. Typage strict avec null safety, asynchrone avec Future, Stream, async et await, isolates pour calculer en parallèle. Dart 3 a ajouté les records, le pattern matching et les sealed classes, très pratiques pour décrire les états d'un écran. Un candidat qui écrit du Dart comme du Java passe à côté de ces outils.
Widgets et moteur de rendu Impeller
Dans Flutter, tout est widget : un texte, une marge, une mise en page, un écran. Le framework reconstruit les widgets à chaque changement d'état, puis met à jour les éléments et le rendu qui en dépendent. Impeller est le moteur de rendu par défaut sur iOS et sur Android (API 29 et plus) depuis Flutter 3.27, et il a supprimé les saccades dues à la compilation des shaders au premier affichage.
Riverpod, Bloc et Provider
La gestion d'état fait débat dans chaque équipe Flutter. Provider est l'ancienne recommandation. Riverpod, aujourd'hui en version 3, gère dépendances, cache et états asynchrones. Bloc sépare événements et états à l'aide de flux. Le choix compte moins que la cohérence du projet et la capacité à expliquer ce qui se reconstruit quand l'état change.
go_router
Le package de navigation maintenu par l'équipe Flutter déclare les routes sous forme d'URL. Il gère les liens profonds, les redirections (vers la connexion par exemple) et la navigation imbriquée sous une barre d'onglets. Les projets plus anciens utilisent encore Navigator directement.
Platform channels, Pigeon et FFI
Pour parler au code natif, Flutter utilise des platform channels (MethodChannel, EventChannel) qui échangent des messages avec Swift ou Kotlin. Pigeon génère ces échanges de façon typée, et dart:ffi appelle directement une bibliothèque C. Savoir écrire un plugin natif sépare un développeur Flutter autonome d'un profil limité aux packages existants.
Firebase et packages pub.dev
Beaucoup d'applications Flutter s'appuient sur Firebase (authentification, Cloud Messaging pour les notifications, Crashlytics, Remote Config) et sur des packages publiés sur pub.dev. Vérifiez que la personne regarde la maintenance et la compatibilité d'un package avant de l'ajouter.
Stockage local
shared_preferences pour les réglages, flutter_secure_storage pour les jetons (trousseau iOS, Keystore Android), SQLite avec drift ou sqflite pour des données structurées. Une application qui doit marcher hors ligne demande en plus une stratégie de synchronisation avec l'API, à faire décrire en entretien.
Tests et outillage
Flutter distingue les tests unitaires, les tests de widgets qui affichent un widget sans appareil, et les tests d'intégration sur émulateur avec integration_test ou Patrol. Les Flutter DevTools montrent les rebuilds, la mémoire et le temps de chaque frame. Codemagic, GitHub Actions ou Fastlane automatisent build et publication.
Flutter sert surtout à des applications iOS et Android, parfois étendues au web ou au desktop avec le même code. Sur une application récente, le développeur passe la plus grande partie de son temps en Dart, entre écrans, état et appels d'API. Sur une réécriture d'application native, il doit aussi lire le Swift ou le Kotlin existant, reprendre ses fonctions natives sous forme de plugins et migrer les données locales des utilisateurs. Une cible web ajoute des sujets absents d'un poste mobile : poids du code chargé, compilation WebAssembly, référencement. Indiquez la cible dans l'offre et construisez l'entretien en conséquence.
Les sujets techniques d'un entretien Flutter
- Dart asynchrone et isolates
- Cycle de vie des widgets et rebuilds
- Gestion d'état (Riverpod, Bloc)
- Platform channels et plugins natifs
- Tests unitaires, de widgets et d'intégration
- Build et publication iOS et Android
Cinq questions Flutter avec la réponse attendue
Chaque question vient avec ce qu'une bonne réponse contient et le signal qui doit vous alerter. Pas besoin d'être technique pour les poser : écoutez si le candidat raconte du vécu.
Question 1 · confirmé
Tout un écran se reconstruit chaque fois qu'un compteur change dans un coin. Comment le voyez-vous, et comment le corrigez-vous ?
Une bonne réponseDans les Flutter DevTools, avec le suivi des rebuilds et la surbrillance des zones redessinées. La correction descend l'état au plus près du widget qui l'affiche : un petit widget qui écoute le compteur (Consumer ou select avec Riverpod, BlocBuilder avec buildWhen, ValueListenableBuilder), des constructeurs const pour les sous-arbres fixes, des widgets extraits en classes plutôt qu'en méthodes qui renvoient des widgets. Un RepaintBoundary isole une zone qui se redessine souvent.
Signal d'alerteUn setState à la racine de l'écran pour tout, ou « Flutter est assez rapide » sans aucune mesure.
Question 2 · confirmé
Le décodage d'un JSON de 5 Mo fige l'interface pendant une seconde. Que faites-vous ?
Une bonne réponseLe code de l'interface tourne sur un seul isolate : un calcul long bloque les frames, même placé dans une fonction async, puisque async ne crée aucun parallélisme. Il déplace le décodage dans un autre isolate avec Isolate.run ou compute, qui renvoie le résultat. Il réduit aussi la réponse côté API (pagination, champs utiles) et sait que les données échangées entre isolates sont en général copiées.
Signal d'alerte« Je mets le décodage dans une fonction async », qui tourne toujours sur le même isolate.
Question 3 · confirmé
Riverpod ou Bloc : sur quels critères choisissez-vous pour une nouvelle application ?
Une bonne réponseIl compare sur des points concrets. Bloc impose des événements et des états explicites, plus verbeux mais lisibles et faciles à tester, souvent apprécié dans les grandes équipes. Riverpod gère l'injection de dépendances, le cache et les états asynchrones (AsyncValue) avec moins de code, sans dépendre du BuildContext. Il cite ce qu'il a utilisé en production, la façon dont il a testé ses états, et l'intérêt de garder une seule approche dans le projet.
Signal d'alerteUn avis tranché sans argument (« Bloc, c'est dépassé »), ou plusieurs solutions mélangées dans la même application sans règle.
Question 4 · senior
L'application doit lire le niveau de batterie et être prévenue quand il change. Aucun package ne convient. Comment l'écrivez-vous ?
Une bonne réponseUn MethodChannel pour la lecture ponctuelle et un EventChannel pour le flux d'événements, avec le code natif en Swift pour iOS et en Kotlin pour Android, rangé dans un plugin. De préférence Pigeon, qui génère des interfaces typées des deux côtés au lieu de chaînes et de Map. Il gère les erreurs natives (PlatformException), le thread sur lequel le code natif répond et l'arrêt de l'écoute quand plus personne n'est abonné.
Signal d'alerteNe pas savoir qu'on peut écrire du code natif, ou un plugin sans gestion d'erreur qui fait planter l'application sur l'une des plateformes.
Question 5 · junior à confirmé
Un widget utilise un TextEditingController et un abonnement à un Stream. Que faites-vous dans dispose, et que se passe-t-il si vous l'oubliez ?
Une bonne réponseIl appelle dispose sur le contrôleur et cancel sur l'abonnement, comme sur les AnimationController, FocusNode et Timer. Sans cela, la mémoire fuit et des callbacks s'exécutent après la destruction de l'écran, avec l'erreur « setState() called after dispose() ». Après un await, il vérifie mounted avant de toucher au BuildContext ou d'appeler setState.
Signal d'alerteAucune idée du cycle de vie d'un StatefulWidget, ou un contrôleur recréé dans build à chaque reconstruction.
Recevez la fiche d'entretien complète en PDF
La fiche pour mener l'entretien de bout en bout, prête à imprimer ou à partager avec le manager.
- 30 questions sur 6 axes, avec la bonne réponse, le signal d'alerte et la relance
- Le niveau visé pour chaque question
- Une mise en situation de 20 minutes et ce qu'on attend du candidat
- La grille d'évaluation de 1 à 4, axe par axe
Bien cadrer un recrutement Flutter
Un développeur Android ou iOS peut-il devenir développeur Flutter ?
Oui, et c'est souvent un bon profil, parce qu'il connaît déjà le cycle de vie mobile, les permissions, la signature et les stores. L'adaptation porte sur Dart, qui s'apprend vite, et sur la logique déclarative des widgets, plus déroutante pour qui a écrit des vues impératives. Vérifiez en entretien la gestion d'état et les rebuilds, où les anciens réflexes se voient le plus. Un développeur Jetpack Compose ou SwiftUI s'y retrouve plus vite.
Quel test technique pour un développeur Flutter ?
Un exercice d'une heure en direct : une liste paginée depuis une API, un écran de détail, des états de chargement et d'erreur, avec la gestion d'état de son choix. Demandez un test de widget sur l'un des écrans. Au débrief, faites expliquer ce qui se reconstruit quand un élément change, puis ce qui se passerait sans réseau. Un projet de plusieurs jours à rendre mesure surtout le temps libre du candidat.
Faut-il exiger le même package de gestion d'état que votre équipe ?
Rarement. Riverpod, Bloc et Provider reposent sur les mêmes notions : séparer l'état de l'affichage, limiter ce qui se reconstruit, tester la logique sans écran. Un développeur confirmé passe de l'un à l'autre en quelques semaines. Exigez-le seulement si le poste commence par la maintenance d'un code existant volumineux. Méfiez-vous plutôt d'un profil qui ne connaît que setState et ne sait pas dire pourquoi il en sortirait.
Flutter Web et desktop font-ils partie du poste ?
Seulement si l'offre le précise. La plupart des postes Flutter restent mobiles. Une cible web ajoute ses propres sujets : poids du code chargé, compilation WebAssembly, référencement limité, bouton retour du navigateur. Une cible desktop ajoute fenêtres, raccourcis clavier et installeurs. Si votre application vise ces plateformes, ajoutez deux ou trois questions dédiées et demandez une application déjà publiée sur la cible concernée.
Pour structurer vos autres entretiens, consultez aussi nos pages sur les questions d'entretien de recrutement, la méthode de l'entretien structuré et la grille d'évaluation d'entretien.





