9 min de lectureMobileArchitecture

Flutter ou natif iOS/Android : comment choisir ?

Expérience, hardware, performance, équipe et maintenance : les critères techniques pour choisir Flutter, Swift et Kotlin sans dogme.

Le choix entre Flutter et le développement natif arrive souvent trop tôt dans un projet mobile. Une idée, quelques écrans, puis une question présentée comme définitive : faut-il partager le code ou construire deux applications séparées ? Posée ainsi, elle masque les contraintes qui comptent vraiment.

La décision porte sur une architecture et son exploitation dans le temps. Elle doit relier l'expérience produit, les API des systèmes, les performances critiques, les compétences disponibles et la façon dont l'équipe livrera chaque version. Flutter comme le natif peuvent être de bons choix ; aucun ne compense un périmètre mal compris.

Ce que vous choisissez réellement

Flutter : une couche produit partagée

Flutter réunit l'interface et une grande partie de la logique applicative dans un projet Dart. Son moteur de rendu apporte un contrôle cohérent sur les composants visuels. Les fonctions propres à iOS et Android passent par des packages ou par des ponts Swift et Kotlin écrits pour le produit.

Partager cette couche ne supprime pas les plateformes. Il faut toujours gérer les permissions, les cycles de vie, la signature, les builds, les notifications et les publications sur chaque store. Flutter réduit surtout la duplication là où le produit se comporte de la même manière.

Swift et Kotlin : un accès direct à chaque plateforme

Une application native utilise les frameworks, composants et outils fournis par Apple ou Google. Les nouvelles API du système sont accessibles sans attendre qu'un package intermédiaire les expose. Les comportements de navigation, d'accessibilité, de tâches en arrière-plan et d'intégration matérielle peuvent être ajustés au plus près de chaque OS.

Deux projets ne signifient pas nécessairement deux produits conçus en silo. Les contrats d'API, les règles métier, le design system, les scénarios de test et la stratégie de mesure peuvent rester communs. En revanche, chaque implémentation demande une ownership et un cycle de livraison explicites.

Les critères qui doivent décider

L'expérience doit-elle être commune ou propre à chaque OS ?

Si iOS et Android partagent les mêmes parcours, le même rythme fonctionnel et une identité visuelle forte, une couche Flutter commune est naturelle. Si la valeur du produit dépend au contraire de composants très spécifiques à la plateforme, d'extensions système ou de conventions différentes, le natif limite les abstractions à maintenir.

Cette question se décide écran par écran et parcours par parcours. Une charte commune n'impose pas des interactions identiques, et une application Flutter peut adapter certains comportements à la plateforme. L'important est d'identifier ces écarts avant qu'ils deviennent une succession d'exceptions.

Quelle est la surface d'intégration native ?

Caméra, Bluetooth, audio, paiements, notifications, biométrie, widgets, partage et exécution en arrière-plan n'ont pas tous le même niveau de maturité dans les bibliothèques multiplateformes. Pour chaque fonction, vérifiez le support des versions d'OS visées, la maintenance du package, les permissions, les modes dégradés et la possibilité de corriger le code natif si nécessaire.

Une intégration spécialisée ne condamne pas automatiquement Flutter. Elle peut devenir un module natif avec une interface Dart étroite et testable. Sur Meduz, l'application Flutter s'appuie ainsi sur des plugins Swift et Kotlin pour dialoguer avec du hardware BLE. Ce découpage garde l'expérience partagée tout en plaçant la contrainte matérielle dans le langage de chaque plateforme.

Où se trouve le risque de performance ?

« Le natif est plus rapide » et « Flutter a les mêmes performances » sont deux raccourcis inutiles. Il faut localiser le chemin critique : démarrage, rendu d'une liste dense, animation, traitement d'image, audio, vidéo, chiffrement, consommation mémoire ou batterie. On prototype ensuite ce chemin sur les appareils réellement visés.

Une lenteur réseau ou backend ne disparaît pas avec Swift ou Kotlin. À l'inverse, une charge de calcul ou une API système difficile à abstraire peut justifier une implémentation native, même si le reste de l'application demeure en Flutter. La mesure doit précéder le verdict.

Qui possédera le produit après la première livraison ?

La composition de l'équipe compte autant que la technologie. Une équipe concentrée autour de Flutter peut faire évoluer les deux plateformes dans un même flux de travail. Deux équipes natives peuvent avancer avec une autonomie forte, à condition d'aligner leurs contrats et leurs priorités. Une organisation qui ne peut relire ni maintenir ses modules natifs crée un risque, même si ces modules sont peu nombreux.

Il faut aussi considérer le recrutement, la revue de code, l'astreinte, la connaissance des stores et le transfert à une autre équipe. Le nombre de dépôts ou de lignes de code n'est pas un coût de possession à lui seul.

De quelles dépendances acceptez-vous le rythme ?

Flutter ajoute le cycle du framework et de ses packages à ceux d'iOS et Android. Le natif dépend directement des changements de chaque SDK. Dans les deux cas, les versions d'OS, les bibliothèques tierces et les règles des stores continuent d'évoluer.

Pour une dépendance critique, documentez son propriétaire, sa fréquence de maintenance, son comportement en cas de rupture et l'effort nécessaire pour la remplacer. Un package pratique sans stratégie de sortie devient vite une décision d'architecture implicite.

Trois architectures possibles, pas seulement deux

Flutter-first

La majorité de l'interface et de la logique applicative est partagée. Les accès natifs passent par des packages sélectionnés ou des plugins internes. Cette approche convient lorsque les parcours restent proches entre plateformes et que l'équipe assume les quelques frontières natives du produit.

Viblyillustre un produit mobile dont les fonctions de feed, chat et billetterie sont portées par une application Flutter commune à iOS et Android. Le choix de la couche mobile reste distinct de celui de l'API et de l'infrastructure.

Natif-first

Chaque plateforme possède son application et adopte directement ses composants, son cycle de vie et ses API. Cette organisation devient cohérente lorsque les expériences divergent réellement, que les fonctions système occupent une place centrale ou que des équipes Swift et Kotlin sont déjà responsables du produit.

Flutter avec îlots natifs

Le produit reste partagé, mais les chemins spécialisés sont isolés dans des modules Swift et Kotlin : BLE, média, traitement intensif ou SDK propriétaire, par exemple. L'interface entre Dart et le natif doit être petite, versionnée et observable. Elle transporte des intentions métier, pas les détails internes de chaque SDK.

Une reprise de produit peut également conserver les frontières qui fonctionnent et remplacer progressivement celles qui posent problème. L'application Flutter de Blisterr et son architecture de streaming LL-HLS/WebRTC montrent pourquoi le choix du client mobile ne doit pas être confondu avec celui des services média et backend.

Valider le choix avec une tranche verticale

Un prototype de navigation ne teste pas le risque principal. Construisez plutôt une tranche mince qui traverse le vrai système : l'écran le plus exigeant, l'API, l'authentification, une intégration native critique, les erreurs et un build distribuable.

  • Testez sur les appareils modestes et les versions d'OS réellement supportées.
  • Couvrez démarrage, passage en arrière-plan, reprise, permissions et interruption réseau.
  • Vérifiez clavier, lecteur d'écran, tailles de texte et navigation sans geste précis.
  • Exécutez les pipelines de signature et de distribution des deux plateformes.
  • Mesurez le chemin critique avec les outils de profiling appropriés.
  • Faites relire le pont natif par la personne qui devra le maintenir.

Cette tranche ne sert pas à déclarer un vainqueur universel. Elle révèle la quantité de code spécifique, les limites des dépendances et la capacité de l'équipe à diagnostiquer le produit complet.

Évaluer le coût de possession, pas seulement le premier build

Comparez le cadrage, l'implémentation, les ponts natifs, la QA par plateforme, les pipelines de livraison, les mises à jour de dépendances et la maintenance opérationnelle. Ajoutez la reprise du code et les compétences nécessaires en cas d'incident. Une base partagée peut réduire certaines duplications sans réduire tous ces postes.

Pour une application existante, le coût de réécriture compte aussi. Avant de migrer, inventoriez les parcours stables, les modules couplés au système, la couverture de tests, les dépendances abandonnées et les données de production disponibles. Une migration progressive est souvent plus maîtrisable qu'un remplacement intégral décidé sur le seul choix du framework.

Les erreurs qui biaisent la décision

  • Choisir Flutter uniquement pour afficher « une seule codebase » dans un budget, sans inventorier le travail propre à chaque plateforme.
  • Choisir le natif par principe sans identifier une contrainte qui profite réellement de cet accès direct.
  • Comparer des démonstrations simples au lieu de prototyper le parcours le plus risqué du produit.
  • Dépendre d'un package critique sans vérifier sa maintenance ni prévoir comment le remplacer.
  • Reporter les tests d'accessibilité, d'arrière-plan et de reprise à la fin du projet.
  • Oublier l'équipe qui maintiendra l'application après sa mise en production.

Checklist de décision

  • Les parcours iOS et Android doivent-ils rester alignés ?
  • Quelles fonctions touchent directement aux API système ?
  • Quels chemins exigent un prototype ou une mesure de performance ?
  • Les packages critiques sont-ils maintenus et remplaçables ?
  • Qui sait développer et diagnostiquer les parties Swift et Kotlin ?
  • Comment les deux plateformes seront-elles testées et publiées ?
  • Quel est le plan de mise à jour des SDK et dépendances ?
  • Le code doit-il rejoindre une équipe existante ou être transféré ?
  • Une migration peut-elle être découpée sans bloquer les versions ?
  • Quelles hypothèses devront être réévaluées après le premier usage ?

Choisir une frontière, pas un camp

Le bon choix n'est pas toujours Flutter ou natif sur la totalité du produit. Une frontière claire peut réserver Swift et Kotlin aux fonctions qui réclament les API des plateformes, tout en partageant l'expérience et la logique qui gagnent réellement à l'être.

Notre service de développement mobile couvre le cadrage, l'architecture et la livraison sur iOS et Android. Si votre décision dépend d'une contrainte hardware, d'une base existante ou d'un parcours difficile à évaluer, parlons-en avant de choisir la stack.