0
0
Fluttermobile~20 mins

Error handling for network calls in Flutter - Mini App: Build & Ship

Choose your learning style9 modes available
Build: Network Error Handling Screen
This screen fetches data from a network and shows it. It handles errors by showing a friendly message and a retry button.
Target UI
┌───────────────────────────────┐
│ Network Data                  │
├───────────────────────────────┤
│ [Loading spinner]              │
│                               │
│                               │
│                               │
│                               │
│                               │
│                               │
└───────────────────────────────┘
Show a loading spinner while fetching data
Display fetched data as text when successful
Show an error message if the network call fails
Provide a Retry button to try fetching data again
Use try-catch to handle exceptions from the network call
Starter Code
Flutter
import 'package:flutter/material.dart';

class NetworkErrorHandlingScreen extends StatefulWidget {
  @override
  State<NetworkErrorHandlingScreen> createState() => _NetworkErrorHandlingScreenState();
}

class _NetworkErrorHandlingScreenState extends State<NetworkErrorHandlingScreen> {
  String? data;
  String? errorMessage;
  bool isLoading = false;

  Future<void> fetchData() async {
    setState(() {
      isLoading = true;
      errorMessage = null;
    });

    // TODO: Add network call with error handling here

    setState(() {
      isLoading = false;
    });
  }

  @override
  void initState() {
    super.initState();
    fetchData();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Network Error Handling')),
      body: Center(
        child: // TODO: Add UI for loading, data, error
      ),
    );
  }
}
Task 1
Task 2
Task 3
Solution
Flutter
import 'package:flutter/material.dart';

class NetworkErrorHandlingScreen extends StatefulWidget {
  @override
  State<NetworkErrorHandlingScreen> createState() => _NetworkErrorHandlingScreenState();
}

class _NetworkErrorHandlingScreenState extends State<NetworkErrorHandlingScreen> {
  String? data;
  String? errorMessage;
  bool isLoading = false;

  Future<void> fetchData() async {
    setState(() {
      isLoading = true;
      errorMessage = null;
      data = null;
    });

    try {
      // Simulate network delay
      await Future.delayed(Duration(seconds: 2));

      // Simulate success or failure randomly
      final success = DateTime.now().second % 2 == 0;

      if (success) {
        data = 'Fetched data from network at ${DateTime.now()}';
      } else {
        throw Exception('Network error occurred');
      }
    } catch (e) {
      errorMessage = e.toString();
    } finally {
      setState(() {
        isLoading = false;
      });
    }
  }

  @override
  void initState() {
    super.initState();
    fetchData();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Network Error Handling')),
      body: Center(
        child: isLoading
            ? CircularProgressIndicator()
            : errorMessage != null
                ? Column(
                    mainAxisSize: MainAxisSize.min,
                    children: [
                      Text('Error: $errorMessage', style: TextStyle(color: Colors.red), textAlign: TextAlign.center),
                      SizedBox(height: 16),
                      ElevatedButton(
                        onPressed: fetchData,
                        child: Text('Retry'),
                      ),
                    ],
                  )
                : Text(data ?? 'No data', textAlign: TextAlign.center),
      ),
    );
  }
}

This solution uses a StatefulWidget to manage the network call state.

Inside fetchData(), we use a try-catch block to simulate a network call that may succeed or fail.

While loading, a spinner is shown. If an error happens, an error message and a Retry button appear. On success, the fetched data text is displayed.

The Retry button calls fetchData() again to try fetching data.

This approach keeps the UI responsive and user-friendly by clearly showing loading, success, and error states.

Final Result
Completed Screen
┌───────────────────────────────┐
│ Network Error Handling        │
├───────────────────────────────┤
│                               │
│   [Loading spinner]            │
│                               │
│                               │
│                               │
│                               │
│                               │
└───────────────────────────────┘

-- OR --

┌───────────────────────────────┐
│ Network Error Handling        │
├───────────────────────────────┤
│                               │
│ Error: Exception: Network     │
│ error occurred                │
│                               │
│      [ Retry Button ]          │
│                               │
└───────────────────────────────┘

-- OR --

┌───────────────────────────────┐
│ Network Error Handling        │
├───────────────────────────────┤
│                               │
│ Fetched data from network at  │
│ 2024-06-01 12:34:56           │
│                               │
│                               │
│                               │
│                               │
└───────────────────────────────┘
When the screen loads, a spinner shows while fetching data.
If the fetch succeeds, the data text appears.
If the fetch fails, an error message and Retry button appear.
Tapping Retry tries fetching data again.
Stretch Goal
Add pull-to-refresh to reload the data by swiping down.
💡 Hint
Wrap the body in a RefreshIndicator widget and call fetchData() on refresh.