Menu
CoddyTech

Zgłaszanie błędu

Część sekcji Dane i sieć ścieżki Flutter w Coddy. Lekcja 11 z 27.

Błędy dotyczą nie tylko serwerów. Twoje własne funkcje mogą odmówić dalszego działania. Gdy funkcja otrzyma coś, z czym nie może pracować, zgłasza wyjątek:

Future<void> saveName(String name) async {
  if (name.isEmpty) {
    throw Exception('The name cannot be empty');
  }
  // zapisz imię
}

throw zatrzymuje funkcję w tym miejscu, podobnie jak return, ale zwraca błąd zamiast wartości. Exception('...') to błąd z komunikatem opisującym, co poszło nie tak.

Funkcja, która ją wywołała, przechwytuje ten błąd za pomocą try i catch, tak samo jak błąd z fetch. Po zamienieniu na tekst Exception zaczyna się od Exception: , po którym następuje Twój komunikat.

Tak działa również prawdziwe fetch. Każda odpowiedź z serwera zawiera kod statusu: 200 oznacza OK, 404 oznacza, że nie znaleziono. Gdy kod statusu nie wynosi 200, Twój kod zgłasza wyjątek, dzięki czemu ekran nigdy nie wyświetla błędnej odpowiedzi tak, jakby były to dane:

final response = await http.get(Uri.parse(url));
if (response.statusCode != 200) {
  throw Exception('The server answered ${response.statusCode}');
}
return response.body;
challenge icon

Wyzwanie

Łatwy

Stuknij Save, gdy pole jest puste: pojawi się Saved: bez imienia. Spraw, aby saveName odrzucała puste imię: po odczekaniu, jeśli name jest puste, rzuć Exception('The name cannot be empty'). Funkcja save już przechwytuje ten wyjątek i wyświetla komunikat.

Spróbuj swoich sił

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 = '';

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

  Future<void> saveName(String name) async {
    await Future.delayed(const Duration(seconds: 1));
  }

  Future<void> save() async {
    try {
      await saveName(controller.text);
      setState(() {
        status = 'Saved: ${controller.text}';
      });
    } 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: save, child: const Text('Save')),
            const SizedBox(height: 16),
            Text(status, style: const TextStyle(fontSize: 18)),
          ],
        ),
      ),
    );
  }
}
quiz iconSprawdź się

Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.

Wszystkie lekcje w sekcji Dane i sieć

Poćwicz samodzielnie: Kompilator Flutter online