18. Exercice sur l'asynchronisme

Jeudi 18/1/24
667 Mots
4 Minutes

5. Exercice

#flutter/blog/flutter/module2

Voici une solution étape par étape pour l'exercice avec l'API catfact.ninja, en expliquant les concepts utilisés et en terminant par le code complet dans un seul fichier Dart.

Étape 1 : Créer la structure de base de l'application

Tout d'abord, nous allons définir la structure minimale de l'application Flutter, comprenant un bouton pour déclencher la récupération d'un nouveau fait sur les chats et un widget Text pour afficher ce fait.

dart
import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Cat Fact App',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const CatFactPage(),
    );
  }
}

Étape 2 : Affichage du fait avec gestion de l'asynchronisme

Nous allons créer la classe CatFactPage, qui va contenir un bouton pour récupérer un nouveau fait et un Text qui affiche ce fait. Nous allons également ajouter une méthode asynchrone pour appeler l'API et récupérer le fait.

dart
class CatFactPage extends StatefulWidget {
  const CatFactPage({Key? key}) : super(key: key);

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

class _CatFactPageState extends State<CatFactPage> {
  String fact = "Cliquez sur le bouton pour obtenir un fait sur les chats";

  Future<void> fetchCatFact() async {
    final response = await http.get(Uri.parse('https://catfact.ninja/fact'));
    if (response.statusCode == 200) {
      final data = jsonDecode(response.body);
      setState(() {
        fact = data['fact'];
      });
    } else {
      setState(() {
        fact = "Erreur lors de la récupération du fait.";
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Cat Fact App'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text(fact, textAlign: TextAlign.center),
            const SizedBox(height: 20),
            ElevatedButton(
              onPressed: fetchCatFact,
              child: const Text('Obtenir un fait'),
            ),
          ],
        ),
      ),
    );
  }
}

Étape 3 : Ajouter les dépendances

Puisque nous utilisons http pour les appels à l'API, nous devons ajouter la dépendance dans notre fichier pubspec.yaml.

yaml
dependencies:
  flutter:
    sdk: flutter
  http: ^0.13.3

Étape 4 : Expliquer le code pas à pas

  1. Appel API Asynchrone : La méthode fetchCatFact est marquée comme async et utilise await pour attendre la réponse de l'API. Si la réponse est un succès (statusCode == 200), nous mettons à jour l'UI avec le fait reçu. Sinon, un message d'erreur est affiché.

  2. Mise à jour de l'UI avec setState : Dès que le fait est récupéré, nous appelons setState pour informer Flutter que l'interface utilisateur doit être reconstruite avec la nouvelle donnée.

  3. Affichage du fait : Nous affichons le fait via un widget Text qui est centré dans la page. Le bouton déclenche la méthode fetchCatFact pour récupérer un nouveau fait à chaque clic.

Étape 5 : Code complet

Voici le code complet de l'application dans un seul fichier Dart :

dart
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Cat Fact App',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const CatFactPage(),
    );
  }
}

class CatFactPage extends StatefulWidget {
  const CatFactPage({Key? key}) : super(key: key);

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

class _CatFactPageState extends State<CatFactPage> {
  String fact = "Cliquez sur le bouton pour obtenir un fait sur les chats";

  Future<void> fetchCatFact() async {
    final response = await http.get(Uri.parse('https://catfact.ninja/fact'));
    if (response.statusCode == 200) {
      final data = jsonDecode(response.body);
      setState(() {
        fact = data['fact'];
      });
    } else {
      setState(() {
        fact = "Erreur lors de la récupération du fait.";
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Cat Fact App'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text(fact, textAlign: TextAlign.center),
            const SizedBox(height: 20),
            ElevatedButton(
              onPressed: fetchCatFact,
              child: const Text('Obtenir un fait'),
            ),
          ],
        ),
      ),
    );
  }
}

Conclusion

Ce projet illustre la gestion des appels asynchrones dans Flutter avec un cas simple d'API. Nous avons utilisé http pour récupérer des faits depuis une API et nous avons géré l'affichage de ces données dans l'interface utilisateur avec un bouton et du texte. Vous pouvez améliorer cette base en ajoutant plus de fonctionnalités ou en utilisant une architecture plus avancée comme Provider ou Riverpod pour mieux gérer l'état.