Utiliser un plug-in avec une application Web Flutter

Flutter est un kit d'interface utilisateur Google qui permet de développer des applications esthétiques compilées de manière native pour les mobiles, le Web et les ordinateurs de bureau, à partir d'un seul codebase. Dans cet atelier de programmation, vous finaliserez une application qui indique le nombre d'étoiles d'un dépôt GitHub. Vous vous servirez des outils pour les développeurs Dart afin d'effectuer quelques opérations simples de débogage. Vous apprendrez comment héberger votre application sur Firebase et utiliserez un plug-in Flutter pour la lancer et ouvrir les règles de confidentialité hébergées.

Points abordés

  • Utiliser un plug-in Flutter dans une application Web
  • Découvrir la différence entre un package et un plug-in
  • Déboguer une application Web à l'aide des outils pour les développeurs Dart
  • Héberger une application sur Firebase

Conditions préalables : nous partons du principe que vous avez des connaissances de base de Flutter. Si vous n'avez jamais utilisé Flutter, commencez par consulter l'article Écrire votre première application Flutter sur le Web.

Qu'attendez-vous de cet atelier de programmation ?

Je suis novice en la matière et je voudrais avoir un bon aperçu. Je connais un peu le sujet, mais j'aimerais revoir certains points. Je recherche un exemple de code à utiliser dans mon projet. Je cherche des explications sur un point spécifique.

Un plug-in (également appelé package de plug-in) est un package Dart spécial qui contient une API écrite en code Dart et une ou plusieurs implémentations spécifiques à une plate-forme. Les packages de plug-ins peuvent être écrits pour Android (avec Kotlin ou Java), iOS (avec Swift ou Objective-C), le Web (avec Dart), macOS (avec Dart) ou une combinaison de ces plate-formes. En fait, Flutter est compatible avec les plug-ins fédérés, qui permettent de répartir la prise en charge de différentes plates-formes sur plusieurs packages.

Un package est une bibliothèque Dart que vous pouvez utiliser pour étendre ou simplifier les fonctionnalités de votre application. Comme nous venons de voir, un plug-in est un type de package. Pour en savoir plus sur les packages et les plug-ins, consultez la page Plug-in Flutter ou package Dart ?

Pour cet atelier, vous avez besoin de trois logiciels : le SDK Flutter, un éditeur et le navigateur Chrome. Vous pouvez utiliser l'éditeur de votre choix, par exemple Android Studio, IntelliJ avec les plug-ins Flutter et Dart, ou Visual Studio Code avec les extensions Dart Code et Flutter. Pour déboguer votre code, vous utiliserez les outils pour les développeurs Dart.

Pour cet atelier de programmation, nous vous fournissons une grande partie du code de démarrage afin que vous puissiez accéder rapidement aux éléments qui vous intéressent.

b2f84ff91b0e1396.pngCréez une application Flutter simple basée sur un modèle.

Créez un projet Flutter appelé star_counter et effectuez une migration vers Null Safety :

$ flutter create star_counter
$ cd star_counter
$ dart migrate --apply-changes

b2f84ff91b0e1396.png Mettez à jour le fichier pubspec.yaml : Mettez à jour le fichier pubspec.yaml à la racine du projet :

pubspec.yaml.

name: star_counter
description: A GitHub Star Counter app
version: 1.0.0+1
environment:
  sdk: ">=2.12.0 <3.0.0"

dependencies:
  flutter:
    sdk: flutter
  flutter_markdown: ^0.6.0
  github: ^8.0.0
  intl: ^0.17.0

dev_dependencies:
  flutter_test:
    sdk: flutter

flutter:
  uses-material-design: true

b2f84ff91b0e1396.png Récupérez les dépendances mises à jour. Cliquez sur le bouton Pub get de votre IDE ou, dans la ligne de commande, exécutez flutter pub get à la racine du projet.

b2f84ff91b0e1396.png Remplacez le contenu de lib/main.dart. Supprimez l'intégralité du code de lib/main.dart qui crée une application Material Design qui compte compter le nombre d'activations d'un bouton. À sa place, ajoutez le code suivant d'une une application pas encore terminée qui indique le nombre d'étoiles d'un dépôt GitHub.

lib/main.dart

import 'package:flutter/material.dart';

void main() {
  runApp(StarCounterApp());
}

class StarCounterApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(
        brightness: Brightness.light,
      ),
      routes: {
        '/': (context) => HomePage(),
      },
    );
  }
}

class HomePage extends StatefulWidget {
  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  String _repositoryName = "";

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: ConstrainedBox(
          constraints: BoxConstraints(maxWidth: 400),
          child: Card(
            child: Padding(
              padding: EdgeInsets.all(16.0),
              child: Column(
                mainAxisSize: MainAxisSize.min,
                crossAxisAlignment: CrossAxisAlignment.center,
                children: [
                  Text(
                    'GitHub Star Counter',
                    style: Theme.of(context).textTheme.headline4,
                  ),
                  TextField(
                    decoration: InputDecoration(
                      labelText: 'Enter a GitHub repository',
                      hintText: 'flutter/flutter',
                    ),
                    onSubmitted: (text) {
                      setState(() {
                        _repositoryName = text;
                      });
                    },
                  ),
                  Padding(
                    padding: const EdgeInsets.only(top: 32.0),
                    child: Text(
                      _repositoryName,
                    ),
                  ),
                ],
              ),
            ),
          ),
        ),
      ),
    );
  }
}

b2f84ff91b0e1396.pngExécutez l'application dans Chrome. Si vous utilisez un IDE, sélectionnez d'abord Chrome dans le menu déroulant des appareils. Si vous utilisez la ligne de commande, exécutez flutter run -d chrome à la racine du package. Si flutter devices indique que le Web est configuré, mais qu'aucun autre appareil n'est connecté, la commande flutter run utilise Chrome par défaut.

Chrome se lance et devrait se présenter comme suit :

97cb2368f34eb03c.png

Saisissez du texte dans le champ de texte, puis appuyez sur Entrée. Le texte que vous avez saisi s'affiche en bas de la fenêtre.

Vous allez maintenant modifier l'application pour qu'elle affiche le nombre d'étoiles de ce dépôt au lieu d'afficher le texte saisi dans le formulaire "google/flutter.widgets".

b2f84ff91b0e1396.pngCréez un fichier nommé star_counter.dart dans lib :

lib/star_counter.dart

import 'package:flutter/material.dart';
import 'package:github/github.dart';
import 'package:intl/intl.dart' as intl;

class GitHubStarCounter extends StatefulWidget {
  /// The full repository name, e.g. torvalds/linux
  final String repositoryName;

  GitHubStarCounter({
    required this.repositoryName,
  });

  @override
  _GitHubStarCounterState createState() => _GitHubStarCounterState();
}

class _GitHubStarCounterState extends State<GitHubStarCounter> {
  // The GitHub API client
  late GitHub github;

  // The repository information
  Repository? repository;

  // A human-readable error when the repository isn't found.
  String? errorMessage;

  void initState() {
    super.initState();
    github = GitHub();

    fetchRepository();
  }

  void didUpdateWidget(GitHubStarCounter oldWidget) {
    super.didUpdateWidget(oldWidget);

    // When this widget's [repositoryName] changes,
    // load the Repository information.
    if (widget.repositoryName == oldWidget.repositoryName) {
      return;
    }

    fetchRepository();
  }

  Future<void> fetchRepository() async {
    setState(() {
      repository = null;
      errorMessage = null;
    });

    if (widget.repositoryName.isNotEmpty) {
      var repo = await github.repositories
          .getRepository(RepositorySlug.full(widget.repositoryName));
      setState(() {
        repository = repo;
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    final textTheme = Theme.of(context).textTheme;
    final textStyle = textTheme.headline4?.apply(color: Colors.green);
    final errorStyle = textTheme.bodyText1?.apply(color: Colors.red);
    final numberFormat = intl.NumberFormat.decimalPattern();

    if (errorMessage != null) {
      return Text(errorMessage!, style: errorStyle);
    }

    if (widget.repositoryName.isNotEmpty && repository == null) {
      return Text('loading...');
    }

    if (repository == null) {
      // If no repository is entered, return an empty widget.
      return SizedBox();
    }

    return Text(
      '${numberFormat.format(repository!.stargazersCount)}',
      style: textStyle,
    );
  }
}

cf1e10b838bf60ee.png Observations

  • Le compteur d'étoiles utilise le package Dart github pour interroger GitHub afin de connaître le nombre d'étoiles que possède un dépôt.
  • Vous pouvez trouver des packages et des plug-ins sur pub.dev.
  • Vous pouvez également parcourir et rechercher les packages proposés pour une plate-forme spécifique. Si vous sélectionnez FLUTTER sur la page de destination, puis WEB sur la page suivante. Cela permet d'afficher les packages qui s'exécutent sur le Web. Vous pouvez parcourir les pages de packages ou utiliser la barre de recherche pour affiner les résultats.
  • La communauté Flutter fournit des packages et des plug-ins dans pub.dev. Si vous consultez la page du package github, vous verrez que celui-ci fonctionne pour presque toute application Dart ou Flutter, y compris pour les applications WEB.
  • Le cas échéant, accordez une attention particulière aux packages signalés comme Favoris Flutter. Le programme Favoris Flutter permet d'identifier les packages qui répondent à des critères spécifiques, tels que l'exhaustivité des fonctionnalités et le bon comportement d'exécution.
  • Par la suite, vous ajouterez un plug-in provenant de pub.dev pour cet exemple.

b2f84ff91b0e1396.png Ajoutez le code import suivant à main.dart :

lib/main.dart

import 'star_counter.dart';

b2f84ff91b0e1396.png Utilisez le nouveau widget GitHubStarCounter.

Dans main.dart, remplacez le widget Text (lignes 60 à 62) par les trois nouvelles lignes qui définissent GitHubStarCounterWidget :

lib/main.dart

Padding(
  padding: const EdgeInsets.only(top: 32.0),
  child: GitHubStarCounter(              // New
    repositoryName: _repositoryName,     // New
  ),                                     // New
),

b2f84ff91b0e1396.png Exécutez l'application.

Redémarrez l'application à chaud sans l'arrêter en cliquant à nouveau sur le bouton Run (Exécuter) de l'IDE. Vous pouvez également cliquer sur le bouton de redémarrage à chaud 293160db29e53878.png dans l'IDE ou saisir r dans la console. Cette opération met à jour l'application sans actualiser le navigateur.

La fenêtre devrait être la même qu'auparavant. Saisissez un dépôt existant, tel que celui suggéré : flutter/flutter. Le nombre d'étoiles s'affiche sous le champ de texte, par exemple :

78a5f531b1acfd58.png

Êtes-vous prêt pour un exercice de débogage ? Dans l'application en cours d'exécution, saisissez un dépôt inexistant, tel que foo/bar. Le widget est bloqué sur Chargement…. Vous allez corriger cela immédiatement.

b2f84ff91b0e1396.png Lancez les outils pour les développeurs Dart.

Vous connaissez sans doute les outils pour les développeurs Chrome, mais pour déboguer une application Flutter, nous vous conseillons d'utiliser les outils pour les développeurs Dart. Ces derniers sont conçus pour le débogage et le profilage des applications Dart et Flutter. Selon votre flux de travail, vous pouvez lancer les outils pour les développeurs Dart de plusieurs façons. Les pages suivantes expliquent comment installer et lancer ces outils :

b2f84ff91b0e1396.png Affichez le débogueur.

La page initiale qui s'affiche lors du lancement des outils pour les développeurs Dart peut varier en fonction de la manière dont ces derniers ont été lancés. Cliquez sur l'onglet Debugger 3d8c8053deda4caa.png (Débogueur) pour afficher le débogueur.

b2f84ff91b0e1396.png Affichez le code source star_counter.dart.

En bas à gauche dans le champ de texte Libraries (Bibliothèques), saisissez star_counter. Double-cliquez sur l'entrée package:star_counter/star_counter.dart dans la liste des résultats pour l'ouvrir dans la vue "Fichier".

b2f84ff91b0e1396.png Définissez un point d'arrêt.

Recherchez la ligne suivante dans la source : var repo = await github.repositories. Elle doit se trouver à la ligne 52. Cliquez à gauche du numéro de ligne. Un cercle s'affiche, ce qui indique que vous avez défini un point d'arrêt. Le point d'arrêt apparaît également dans la liste Breakpoints (Points d'arrêt) sur la gauche. En haut à droite, cochez la case Break on exceptions (Arrêter l'exécution en cas d'exception). L'interface utilisateur devrait se présenter comme suit :

eeec16d42e7012ba.png

b2f84ff91b0e1396.png Exécutez l'application.

Saisissez un dépôt inexistant, puis appuyez sur Entrée. Dans le volet d'erreur, situé en dessous du volet du code, vous verrez que le package github a renvoyé une exception "Dépôt introuvable" :

Error: GitHub Error: Repository Not Found: /
    at Object.throw_ [as throw] (http://localhost:52956/dart_sdk.js:4463:11)
    at http://localhost:52956/packages/github/src/common/xplat_common.dart.lib.js:1351:25
    at github.GitHub.new.request (http://localhost:52956/packages/github/src/common/xplat_common.dart.lib.js:10679:13)
    at request.next (<anonymous>)
    at http://localhost:52956/dart_sdk.js:37175:33
    at _RootZone.runUnary (http://localhost:52956/dart_sdk.js:37029:58)
    at _FutureListener.thenAwait.handleValue (http://localhost:52956/dart_sdk.js:32116:29)
    at handleValueCallback (http://localhost:52956/dart_sdk.js:32663:49)
    at Function._propagateToListeners (http://localhost:52956/dart_sdk.js:32701:17)
    at _Future.new.[_completeWithValue] (http://localhost:52956/dart_sdk.js:32544:23)
    at async._AsyncCallbackEntry.new.callback (http://localhost:52956/dart_sdk.js:32566:35)
    at Object._microtaskLoop (http://localhost:52956/dart_sdk.js:37290:13)
    at _startMicrotaskLoop (http://localhost:52956/dart_sdk.js:37296:13)
    at http://localhost:52956/dart_sdk.js:32918:9

b2f84ff91b0e1396.png Identifiez l'erreur.

Dans star_counter.dart, recherchez le code suivant (lignes 52 à 58) :

if (widget.repositoryName.isNotEmpty) {
  var repo = await github.repositories
      .getRepository(RepositorySlug.full(widget.repositoryName));
  setState(() {
    repository = repo;
  });
}

Remplacez-le par un code faisant appel à un bloc try-catch de sorte qu'il intercepte l'erreur et qu'il affiche un message :

lib/star_counter.dart

if (widget.repositoryName.isNotEmpty) {
  try {
    var repo = await github.repositories
        .getRepository(RepositorySlug.full(widget.repositoryName));
    setState(() {
      repository = repo;
    });
  } on RepositoryNotFound {
    setState(() {
      repository = null;
      errorMessage = '${widget.repositoryName} not found.';
    });
  }
}

b2f84ff91b0e1396.png Redémarrez l'application à chaud.

Dans les outils de développement, le code source est mis à jour pour refléter les modifications. Une fois encore, saisissez un dépôt inexistant. La page suivante doit normalement s'afficher :

f1b3847ee101a85b.png

f5077295022a18df.pngVous avez trouvé une pièce du puzzle !

Au cours de cette étape, vous allez ajouter une page concernant les règles de confidentialité à votre application. Dans un premier temps, vous allez intégrer le texte des règles de confidentialité dans votre code Dart.

b2f84ff91b0e1396.png Ajoutez un fichier lib/privacy_policy.dart. Dans le répertoire lib, ajoutez un fichier privacy_policy.dart à votre projet :

lib/privacy_policy.dart

import 'package:flutter/widgets.dart';
import 'package:flutter_markdown/flutter_markdown.dart';

class PrivacyPolicy extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Markdown(
      data: _privacyPolicyText,
    );
  }
}

// The source for this privacy policy was generated by
// https://app-privacy-policy-generator.firebaseapp.com/
var _privacyPolicyText = '''
## Privacy Policy

Flutter Example Company built the Star Counter app as an Open Source app. This SERVICE is provided by Flutter Example Company at no cost and is intended for use as is.

This page is used to inform visitors regarding our policies with the collection, use, and disclosure of Personal Information if anyone decided to use our Service.

If you choose to use our Service, then you agree to the collection and use of information in relation to this policy. The Personal Information that we collect is used for providing and improving the Service. We will not use or share your information with anyone except as described in this Privacy Policy.

The terms used in this Privacy Policy have the same meanings as in our Terms and Conditions, which is accessible at Star Counter unless otherwise defined in this Privacy Policy.
''';

b2f84ff91b0e1396.png Ajoutez le code import suivant à main.dart :

lib/main.dart

import 'privacy_policy.dart';

b2f84ff91b0e1396.png Ajoutez une route (une page) vers les règles de confidentialité.

Après la ligne 17, ajoutez la route vers la page des règles de confidentialité :

lib/main.dart

routes: {
  '/': (context) => HomePage(),
  '/privacypolicy': (context) => PrivacyPolicy(),  // NEW
},

b2f84ff91b0e1396.png Ajoutez un bouton pour afficher les règles de confidentialité.

Dans la méthode build() de _HomePageState, ajoutez un TextButton en bas de Column, après la ligne 65 :

lib/main.dart

TextButton(
  style: ButtonStyle(
    foregroundColor: MaterialStateProperty.all(Colors.blue),
    overlayColor: MaterialStateProperty.all(Colors.transparent),
  ),
  onPressed: () => Navigator.of(context).pushNamed('/privacypolicy'),
  child: Text('Privacy Policy'),
),

b2f84ff91b0e1396.png Exécutez l'application.

Redémarrez l'application à chaud. Elle comporte désormais un lien Privacy Policy (Règles de confidentialité) en bas de l'écran :

ae990c7f6e0918e5.png

b2f84ff91b0e1396.png Cliquez sur le bouton Privacy Policy (Règles de confidentialité).

Notez que les règles de confidentialité s'affichent et que l'URL passe à /privacypolicy.

C233a1dea9abfaec.png

b2f84ff91b0e1396.png Revenez en arrière.

Utilisez le bouton Retour du navigateur pour revenir à la première page. Ce comportement est fourni sans nécessiter de configuration.

L'avantage d'une page hébergée est que vous pouvez la modifier sans avoir à publier une nouvelle version de votre application.

À partir de la ligne de commande, au répertoire racine du projet, suivez ces instructions :

b2f84ff91b0e1396.png Installez CLI Firebase.

b2f84ff91b0e1396.png Connectez-vous à Firebase pour vous authentifier à l'aide de firebase login.

b2f84ff91b0e1396.png Initialisez un projet Firebase à l'aide de firebase init.

Utilisez les valeurs suivantes :

  • Quelles fonctionnalités Firebase ? Hosting
  • Configuration du projet : Créer un projet
  • Quel nom attribuer au projet ? [yourname]-my-flutter-app (le nom doit être unique)
  • Comment appeler le projet ? Appuyez sur Entrée pour accepter la valeur par défaut (identique au nom attribué dans la question précédente).
  • Quel répertoire public ? build/web (important)
  • Configurer en tant qu'application monopage ? Oui
  • Configurer les builds et les déploiements automatiques avec GitHub ? Non

Une fois que vous avez exécuté firebase init, la ligne de commande devrait se présenter comme suit :

55135b9eda3c41ef.png

Lors de l'exécution de la commande init, les fichiers suivants sont ajoutés à votre projet :

  • firebase.json (fichier de configuration)
  • .firebaserc (fichier contenant les données de votre projet)

Assurez-vous que le champ public de votre fichier firebase.json spécifie build/web, par exemple :

firebase.json

{
  "hosting": {
    "public": "build/web",    # This is important!
    "ignore": [
      "firebase.json",
      "**/.*",
      "**/node_modules/**"
    ],
    "rewrites": [
      {
        "source": "**",
        "destination": "/index.html"
      }
    ]
  }
}

b2f84ff91b0e1396.png Créez une version de votre application.

Configurez votre IDE pour créer une version de votre application selon l'une des méthodes suivantes :

  • Dans Android Studio ou IntelliJ, spécifiez --release dans le champ Additional arguments (Arguments supplémentaires) de la boîte de dialogue Run (Exécuter) > Edit Configuration (Modifier la configuration). Exécutez ensuite votre application.
  • Dans la ligne de commande, exécutez flutter build web --release.

Vérifiez que cette étape a bien fonctionné en examinant le répertoire build/web de votre projet. Celui-ci doit contenir un certain nombre de fichiers, dont index.html.

b2f84ff91b0e1396.png Déployez votre application.

Dans la ligne de commande, exécutez firebase deploy à la racine du projet pour déployer le contenu du répertoire public build/web. Cela permet d'afficher l'URL où l'application est hébergée, soit https://project-id>.web.app.

Dans le navigateur, accédez à https://<project-id>.web.app ou https://<project-id>.web.app/#/privacypolicy pour afficher la version de vos règles de confidentialité.

Au lieu d'intégrer vos règles de confidentialité dans le code de Dart, vous les hébergerez en tant que page HTML à l'aide de Firebase.

b2f84ff91b0e1396.png Supprimez privacy_policy.dart.

Supprimez le fichier du répertoire lib de votre projet.

b2f84ff91b0e1396.png Mettez à jour main.dart.

Dans lib/main.dart, supprimez l'instruction d'importation import privacy_policy.dart et le widget PrivacyPolicyPage situé au bas de l'écran.

b2f84ff91b0e1396.png Ajoutez privacy_policy.html.

Placez ce fichier dans le répertoire web de votre projet.

web/privacy_policy.html

<!doctype html>

<html lang="en">
<head>
  <meta charset="utf-8">

  <title>Privacy Policy</title>
</head>

<body>
<h2 id="privacy-policy">Privacy Policy</h2>
<p>Flutter Example Company built the Star Counter app as an Open Source app. This SERVICE is provided by Flutter Example Company at no cost and is intended for use as is.</p>
<p>This page is used to inform visitors regarding our policies with the collection, use, and disclosure of Personal Information if anyone decided to use our Service.</p>
<p>If you choose to use our Service, then you agree to the collection and use of information in relation to this policy. The Personal Information that we collect is used for providing and improving the Service. We will not use or share your information with anyone except as described in this Privacy Policy.</p>
<p>The terms used in this Privacy Policy have the same meanings as in our Terms and Conditions, which is accessible at Star Counter unless otherwise defined in this Privacy Policy.</p>
</body>
</html>

Ensuite, utilisez le plug-in url_launcher pour ouvrir les règles de confidentialité dans un nouvel onglet.

Les applications Web Flutter sont des applications monopage (SPA). C'est pourquoi le mécanisme de routage standard dans notre exemple Web ouvre les règles de confidentialité sur la même page Web. En revanche, le plug-in de lancement d'URL ouvre un nouvel onglet dans le navigateur, avant de lancer une autre copie de l'application et d'acheminer l'application vers la page hébergée.

b2f84ff91b0e1396.png Ajoutez une dépendance.

Dans le fichier pubspec.yaml, ajoutez la dépendance suivante. N'oubliez pas que les espaces sont importantes dans un fichier YAML. Assurez-vous donc que la ligne commence par deux espaces vides :

pubspec.yaml.

  url_launcher: ^6.0.0

b2f84ff91b0e1396.png Récupérez la nouvelle dépendance.

Arrêtez l'application, car l'ajout d'une dépendance nécessite un redémarrage complet. Cliquez sur le bouton Pub get de l'IDE ou, dans la ligne de commande, exécutez flutter pub get à la racine du projet.

b2f84ff91b0e1396.png Ajoutez le code import suivant à main.dart :

lib/main.dart

import 'package:url_launcher/url_launcher.dart';

b2f84ff91b0e1396.png Mettez à jour le gestionnaire de TextButton.

Toujours dans main.dart, remplacez le code appelé lorsque l'utilisateur appuie sur le bouton Privacy Policy (Règles de confidentialité). Le code d'origine (à la ligne 71) utilise le mécanisme de routage normal de Flutter :

onPressed: () => Navigator.of(context).pushNamed('/privacypolicy'),

Le nouveau code de onPressed appelle le package url_launcher :

lib/main.dart

onPressed: () => launch(
  '/privacy_policy.html',
  enableJavaScript: true,
  enableDomStorage: true,
),

b2f84ff91b0e1396.png Exécutez l'application.

Cliquez sur le bouton Privacy Policy (Règles de confidentialité) pour ouvrir le fichier dans un nouvel onglet. Le principal avantage du package url_launcher est qu'une fois la page des règles de confidentialité hébergée, il fonctionne à la fois sur les plates-formes Web et mobiles. Autre avantage : vous pouvez modifier la page des règles de confidentialité hébergée sans avoir à recompiler votre application.

Une fois votre projet terminé, n'oubliez pas de le nettoyer :

b2f84ff91b0e1396.png Supprimez votre projet Firebase.

Félicitations, vous avez finalisé votre application de compteur d'étoiles sur GitHub ! Vous avez également eu un aperçu des outils pour les développeurs Dart, que vous pouvez utiliser pour déboguer et profiler toutes les applications Dart et Flutter, et pas seulement les applications Web.

Et ensuite ?

Pour aller plus loin dans votre apprentissage de Flutter :