Error Handling
When working with remote data in Flutter, error handling is critical because network requests are inherently unreliable. Issues like lost connectivity, invalid responses, or server errors can disrupt the user experience or cause your app to crash if not managed properly. By implementing robust error handling, you ensure your app remains stable, users are informed of problems, and sensitive operations can be retried or gracefully degraded.
main.dart
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667import 'package:flutter/material.dart'; import 'package:dio/dio.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( title: 'Dio Error Handling Demo', home: Scaffold( appBar: AppBar(title: const Text('Network Error Example')), body: const Center(child: NetworkRequestWidget()), ), ); } } class NetworkRequestWidget extends StatefulWidget { const NetworkRequestWidget({super.key}); @override State<NetworkRequestWidget> createState() => _NetworkRequestWidgetState(); } class _NetworkRequestWidgetState extends State<NetworkRequestWidget> { String _result = "Press the button to fetch data."; Future<void> _fetchData() async { final dio = Dio(); setState(() { _result = "Loading..."; }); try { // Intentionally using an invalid URL to trigger an error final response = await dio.get('https://invalid.url.com/data'); setState(() { _result = response.data.toString(); }); } on DioException catch (e) { setState(() { _result = "Network error: ${e.message}"; }); } catch (e) { setState(() { _result = "Unexpected error: $e"; }); } } @override Widget build(BuildContext context) { return Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text(_result, textAlign: TextAlign.center), const SizedBox(height: 20), ElevatedButton( onPressed: _fetchData, child: const Text('Fetch Data'), ), ], ); } }
Providing clear user feedback is essential when network errors occur. In the previous example, the app displays an error message to inform users when a network request fails, which helps prevent confusion and frustration. For a better experience, consider adding retry strategies so users can attempt the operation again without restarting the app. This approach can be as simple as offering a Retry button, or you can implement automatic retries with exponential backoff for more advanced scenarios. The next example demonstrates a straightforward retry mechanism for failed network requests.
main.dart
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778import 'package:flutter/material.dart'; import 'package:dio/dio.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( title: 'Retry Network Request Demo', home: Scaffold( appBar: AppBar(title: const Text('Retry Mechanism Example')), body: const Center(child: RetryNetworkWidget()), ), ); } } class RetryNetworkWidget extends StatefulWidget { const RetryNetworkWidget({super.key}); @override State<RetryNetworkWidget> createState() => _RetryNetworkWidgetState(); } class _RetryNetworkWidgetState extends State<RetryNetworkWidget> { String _result = "Press the button to fetch data."; int _retryCount = 0; static const int maxRetries = 3; Future<void> _fetchDataWithRetry() async { final dio = Dio(); int attempt = 0; setState(() { _result = "Loading..."; _retryCount = 0; }); while (attempt < maxRetries) { try { // Intentionally using an invalid URL to trigger an error final response = await dio.get('https://invalid.url.com/data'); setState(() { _result = response.data.toString(); }); return; } on DioException catch (e) { attempt++; setState(() { _retryCount = attempt; }); if (attempt >= maxRetries) { setState(() { _result = "Failed after $attempt attempts: ${e.message}"; }); } } } } @override Widget build(BuildContext context) { return Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text(_result, textAlign: TextAlign.center), if (_retryCount > 0 && _retryCount < maxRetries) Text("Retrying... ($_retryCount/$maxRetries)"), const SizedBox(height: 20), ElevatedButton( onPressed: _fetchDataWithRetry, child: const Text('Fetch Data with Retry'), ), ], ); } }
Takk for tilbakemeldingene dine!
Spør AI
Spør AI
Spør om hva du vil, eller prøv ett av de foreslåtte spørsmålene for å starte chatten vår
Fantastisk!
Completion rate forbedret til 9.09
Error Handling
Sveip for å vise menyen
When working with remote data in Flutter, error handling is critical because network requests are inherently unreliable. Issues like lost connectivity, invalid responses, or server errors can disrupt the user experience or cause your app to crash if not managed properly. By implementing robust error handling, you ensure your app remains stable, users are informed of problems, and sensitive operations can be retried or gracefully degraded.
main.dart
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667import 'package:flutter/material.dart'; import 'package:dio/dio.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( title: 'Dio Error Handling Demo', home: Scaffold( appBar: AppBar(title: const Text('Network Error Example')), body: const Center(child: NetworkRequestWidget()), ), ); } } class NetworkRequestWidget extends StatefulWidget { const NetworkRequestWidget({super.key}); @override State<NetworkRequestWidget> createState() => _NetworkRequestWidgetState(); } class _NetworkRequestWidgetState extends State<NetworkRequestWidget> { String _result = "Press the button to fetch data."; Future<void> _fetchData() async { final dio = Dio(); setState(() { _result = "Loading..."; }); try { // Intentionally using an invalid URL to trigger an error final response = await dio.get('https://invalid.url.com/data'); setState(() { _result = response.data.toString(); }); } on DioException catch (e) { setState(() { _result = "Network error: ${e.message}"; }); } catch (e) { setState(() { _result = "Unexpected error: $e"; }); } } @override Widget build(BuildContext context) { return Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text(_result, textAlign: TextAlign.center), const SizedBox(height: 20), ElevatedButton( onPressed: _fetchData, child: const Text('Fetch Data'), ), ], ); } }
Providing clear user feedback is essential when network errors occur. In the previous example, the app displays an error message to inform users when a network request fails, which helps prevent confusion and frustration. For a better experience, consider adding retry strategies so users can attempt the operation again without restarting the app. This approach can be as simple as offering a Retry button, or you can implement automatic retries with exponential backoff for more advanced scenarios. The next example demonstrates a straightforward retry mechanism for failed network requests.
main.dart
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778import 'package:flutter/material.dart'; import 'package:dio/dio.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( title: 'Retry Network Request Demo', home: Scaffold( appBar: AppBar(title: const Text('Retry Mechanism Example')), body: const Center(child: RetryNetworkWidget()), ), ); } } class RetryNetworkWidget extends StatefulWidget { const RetryNetworkWidget({super.key}); @override State<RetryNetworkWidget> createState() => _RetryNetworkWidgetState(); } class _RetryNetworkWidgetState extends State<RetryNetworkWidget> { String _result = "Press the button to fetch data."; int _retryCount = 0; static const int maxRetries = 3; Future<void> _fetchDataWithRetry() async { final dio = Dio(); int attempt = 0; setState(() { _result = "Loading..."; _retryCount = 0; }); while (attempt < maxRetries) { try { // Intentionally using an invalid URL to trigger an error final response = await dio.get('https://invalid.url.com/data'); setState(() { _result = response.data.toString(); }); return; } on DioException catch (e) { attempt++; setState(() { _retryCount = attempt; }); if (attempt >= maxRetries) { setState(() { _result = "Failed after $attempt attempts: ${e.message}"; }); } } } } @override Widget build(BuildContext context) { return Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text(_result, textAlign: TextAlign.center), if (_retryCount > 0 && _retryCount < maxRetries) Text("Retrying... ($_retryCount/$maxRetries)"), const SizedBox(height: 20), ElevatedButton( onPressed: _fetchDataWithRetry, child: const Text('Fetch Data with Retry'), ), ], ); } }
Takk for tilbakemeldingene dine!