Error Handling in Flutter Using runZonedGuarded and Global Error Catching

Created At: 2025-03-29 22:49:45 Updated At: 2025-03-29 23:42:41

🚀 Error Handling in Flutter Using runZonedGuarded and Global Error Catching 🔥

Flutter provides powerful mechanisms to handle errors gracefully, ensuring a smooth user experience even when unexpected issues arise. This article explores how to use runZonedGuarded and global error handling techniques in a Flutter application. 🌟

Overview of the Implementation

The given Flutter application uses:

  • A GlobalKey to manage navigation and error screens.

  • FlutterError.onError to catch framework errors.

  • runZonedGuarded to capture errors occurring outside the Flutter framework.

  • A dedicated ErrorScreen to display unexpected error messages.

Code Breakdown 

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

final GlobalKey navigatorKey = GlobalKey();

void main() {
  // Handling Flutter framework errors
  FlutterError.onError = (FlutterErrorDetails details) {
    WidgetsBinding.instance.addPostFrameCallback((_) {
      if (navigatorKey.currentState?.overlay?.context.widget is! ErrorScreen) {
        navigatorKey.currentState?.pushReplacement(
          MaterialPageRoute(
            builder: (context) => ErrorScreen(errorDetails: details),
          ),
        );
      }
    });
  };

  // Handling all uncaught errors
  runZonedGuarded(() => runApp(MyApp()), (error, stackTrace) {
    debugPrint("Caught error in runZonedGuarded: $error");
  });
}

 

Understanding runZonedGuarded 

The function runZonedGuarded provides an execution zone where any uncaught runtime exceptions are intercepted, allowing developers to log or handle errors effectively.

Syntax:

runZonedGuarded(
  () => runApp(MyApp()),
  (error, stackTrace) {
    debugPrint("Error caught: $error");
  }
);

 

Why Use runZonedGuarded

  1. Captures errors outside the Flutter framework – If an error occurs in asynchronous tasks like network requests or database operations, runZonedGuarded ensures it doesn’t crash the app silently.

  2. Prevents app crashes – Instead of the app terminating unexpectedly, errors can be logged or redirected to an error reporting tool.

Handling Flutter Framework Errors 

Flutter provides FlutterError.onError to catch exceptions occurring within the Flutter widget tree.

FlutterError.onError = (FlutterErrorDetails details) {
  WidgetsBinding.instance.addPostFrameCallback((_) {
    if (navigatorKey.currentState?.overlay?.context.widget is! ErrorScreen) {
      navigatorKey.currentState?.pushReplacement(
        MaterialPageRoute(
          builder: (context) => ErrorScreen(errorDetails: details),
        ),
      );
    }
  });
};

 

Explanation: 

  • The function captures Flutter framework errors.

  • A new ErrorScreen is displayed, replacing the current screen, so users don’t experience app crashes.

  • WidgetsBinding.instance.addPostFrameCallback ensures the navigation occurs after the current frame renders.

Demonstrating an Error Scenario 

The NewScreen widget contains a forced error:

class NewScreen extends StatelessWidget {
  const NewScreen({super.key, required this.x});
  final int? x;
  
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('New Screen')),
      body: Center(
        child: ElevatedButton(
          onPressed: () => Navigator.of(context).pop(),
          child: Text('${x! + 10}'),
        ),
      ),
    );
  }
}

Here, x is explicitly null, and x! + 10 will throw an error when tapped. Since this error is in the widget tree, FlutterError.onError will catch it and navigate to ErrorScreen

Displaying the Error Screen 

class ErrorScreen extends StatelessWidget {
  final FlutterErrorDetails errorDetails;
  const ErrorScreen({required this.errorDetails, super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text("Oops! Something went wrong")),
      body: Center(
        child: Text(errorDetails.exceptionAsString(), textAlign: TextAlign.center),
      ),
    );
  }
}

This screen provides a user-friendly message instead of crashing the app. 

Conclusion 

Using runZonedGuarded and FlutterError.onError ensures:

  • Errors do not lead to unexpected crashes.

  • Issues are logged and can be displayed to users.

  • The app remains stable, improving the overall user experience. 

By implementing these techniques, developers can handle unexpected failures efficiently, making their Flutter apps more resilient and reliable. 

Comment

Add Reviews

1
Chat With Us