Menu
CoddyTech

Nettoyer avec finally

Fait partie de la section Données et réseau du Journey Flutter de Coddy. Leçon 12 sur 27.

Certaines tâches doivent être effectuées, que l’appel réussisse ou échoue : masquer l’indicateur de chargement, réactiver un bouton. Écrire cela à la fois dans try et dans catch peut facilement être oublié dans l’un des deux blocs. Dart dispose d’un troisième bloc pour cela, finally :

try {
  await saveName(name);
} catch (e) {
  // afficher l'erreur
} finally {
  // toujours exécuté : après try ou après catch
}

finally s’exécute en dernier, à chaque fois : après try si l’appel a réussi, après catch s’il a échoué. C’est donc l’endroit idéal pour annuler ce que tu as préparé avant l’appel.

Ici, l’application grise le bouton Enregistrer pendant l’enregistrement, avec onPressed: saving ? null : save. Un bouton dont le onPressed vaut null ne peut pas être pressé. Si saving ne repasse jamais à false, le bouton reste définitivement grisé.

challenge icon

Défi

Moyen

Enregistrez avec un champ vide : l’erreur s’affiche et le bouton Enregistrer reste grisé, vous ne pouvez donc jamais réessayer. Déplacez saving = false du bloc try vers un bloc finally, dans son propre setState.

Essayez vous-même

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      debugShowCheckedModeBanner: false,
      home: NameScreen(),
    );
  }
}

class NameScreen extends StatefulWidget {
  const NameScreen({super.key});

  @override
  State<NameScreen> createState() => _NameScreenState();
}

class _NameScreenState extends State<NameScreen> {
  final controller = TextEditingController();
  String status = '';
  bool saving = false;

  @override
  void dispose() {
    controller.dispose();
    super.dispose();
  }

  Future<void> saveName(String name) async {
    await Future.delayed(const Duration(seconds: 1));
    if (name.isEmpty) {
      throw Exception('The name cannot be empty');
    }
  }

  Future<void> save() async {
    setState(() {
      saving = true;
    });
    try {
      await saveName(controller.text);
      setState(() {
        status = 'Saved: ${controller.text}';
        saving = false;
      });
    } catch (e) {
      setState(() {
        status = '$e';
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Padding(
        padding: const EdgeInsets.all(24),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            TextField(
              controller: controller,
              decoration: const InputDecoration(labelText: 'Name'),
            ),
            const SizedBox(height: 16),
            ElevatedButton(onPressed: saving ? null : save, child: const Text('Save')),
            const SizedBox(height: 16),
            Text(status, style: const TextStyle(fontSize: 18)),
          ],
        ),
      ),
    );
  }
}
quiz iconTestez-vous

Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.

Toutes les leçons de Données et réseau

Entraînez-vous par vous-même : Compilateur Flutter en ligne