Flutter错误处理或增强插件error_or_plus的使用

发布于 1周前 作者 eggper 来自 Flutter

Flutter错误处理或增强插件error_or_plus的使用

整理后的内容

  1. 安装插件

    dart pub add error_or_plus
    
  2. 替换抛出异常为ErrorOr<T>

double divide(int a, int b) {
  if (b == 0 ) {
    return Errors.unexpected(description: "Cannot divide by zero");
  }

  return a / b;
}

var result = divide(4, 2);

if (result.isError) {
  print(result.firstError.description);
  return;
}

print(result.value * 2); // 4
  1. 支持多个错误
class User {
  final String _name;

  User._internal(this._name);

  static ErrorOr&lt;User&gt; create(String name) {
    List&lt;Errors&gt; errors = [];

    if (name.length &lt; 2) {
      errors.add(Errors.validation(description: "Name is too short"));
    }

    if (name.length &gt; 100) {
      errors.add(Errors.validation(description: "Name is too long"));
    }

    if (name.isEmpty) {
      errors.add(Errors.validation(
          description: "Name cannot be empty or whitespace only"));
    }

    if (errors.isNotEmpty) {
      return errors.toErrorOr&lt;User&gt;();
    }

    return User._internal(name).toErrorOr();
  }
}
  1. 各种功能方法和扩展方法

  2. 创建一个ErrorOr实例

ErrorOr&lt;int&gt; result = 5.ToErrorOr();
ErrorOr&lt;int&gt; result = Errors.unexpected().ToErrorOr&lt;int&gt;();
ErrorOr&lt;int&gt; result = [Errors.validation(), Errors.validation()].ToErrorOr&lt;int&gt;();
  1. 属性
  • isError

    if (result.isError {
      // 结果包含一个或多个错误
    }
    
  • value

    if (!result.isError) { // 结果包含一个值
      print(result.value);
    }
    
  • errors

    if (result.isError) {
      result.errors // 包含发生的所有错误
          .forEach((error) =&gt; print(error.description));
    }
    
  • firstError

    if (result.isError) {
      var firstError = result.firstError; // 只有第一个发生的错误
      print(firstError == result.errors[0]); // true
    }
    
  • errorsOrEmptyList

    if (result.isError) {
      result.errorsOrEmptyList // List&lt;Errors&gt; { /* 一个或多个错误 */ }
      return;
    }
    
    result.errorsOrEmptyList // List&lt;Errors&gt; { }
    
  1. 方法
  • match

    String foo = result.match(
        (value) =&gt; value,
        (errors) =&gt; "${errors.Count} errors occurred.");
    
  • matchAsync

    String foo = await result.matchAsync(
        (value) =&gt; Future.value(value),
        (errors) =&gt; Future.value("${errors.Count} errors occurred."));
    
  • matchFirst

    String foo = result.matchFirst(
        (value) =&gt; value,
        (firstError) =&gt; firstError.description);
    
  • matchFirstAsync

    String foo = await result.matchFirstAsync(
        (value) =&gt; Future.value(value),
        (firstError) =&gt; Future.value(firstError.description));
    
  • doSwitch

    result.doSwitch(
        (value) =&gt; print(value),
        (errors) =&gt; print("${errors.Count} errors occurred."));
    
  • doSwitchAsync

    await result.doSwitchAsync(
        (value) { print(value); return Future.value(true); },
        (errors) { print("${errors.Count} errors occurred."); return Future.value(true); });
    
  • doSwitchFirst

    result.doSwitchFirst(
        (value) =&gt; print(value),
        (firstError) =&gt; print(firstError.description));
    
  • doSwitchFirstAsync

    await result.doSwitchFirstAsync(
        (value) { print(value); return Future.value(true); },
        (firstError) { print(firstError.description); return Future.value(true); });
    
  • also

    ErrorOr&lt;int&gt; foo = result
        .also((val) =&gt; val * 2);
    
  • alsoAsync

    ErrorOr&lt;String&gt; foo = await result
        .alsoAsync((val) =&gt; doSomethingAsync(val))
        .alsoAsync((val) =&gt; doSomethingElseAsync("The result is ${val}"));
    
  • alsoDo

    ErrorOr&lt;String&gt; foo = result
        .alsoDo((val) =&gt; print(val))
        .alsoDo((val) =&gt; print("The result is ${val}");
    
  • alsoDoAsync

    ErrorOr&lt;String&gt; foo = await result
        .alsoDoAsync((val) =&gt; Future.delayed(Duration(milliseconds: val)))
        .alsoDo((val) =&gt; print("Finsihed waiting ${val} seconds."))
        .alsoDoAsync((val) =&gt; Future.value(val * 2))
        .alsoDo((val) =&gt "The result is ${val}");
    
  • failIf

    ErrorOr&lt;int&gt; foo = result
        .failIf((val) =&gt; val &gt; 2, Errors.validation(description: "${val} is too big"));
    
  • orElse

    ErrorOr&lt;String&gt; foo = result
        .orElse(valueOnErrorHandler: "fallback value");
    
  • orelseAsync

    ErrorOr&lt;String&gt; foo = await result
        .orElseAsync(valueOnErrorHandler: Future.value("fallback value"));
    
  • mixing also-also-do-alsoasync-alsoDoasync

    ErrorOr&lt;String&gt; foo = await result
        .alsoDoAsync((val) =&gt Future.delayed(Duration(milliseconds: val)))
        .failIf((val) =&gt; val &gt; 2, Errors.validation(description: "${val} is too big"))
        .alsoDo((val) =&gt print("Finished waiting ${val} seconds."))
        .alsoAsync((val) =&gt Future.value(val * 2))
        .also((val) =&gt "The result is ${val}")
        .orElse(errorOnErrorHandler: (errors) =&gt Errors.unexpected())
        .matchFirst(
            (value) =&gt value,
            (firstError) =&gt "An error occurred: {firstError.description}");
    
  1. 错误类型

每个Errors实例都有一个Type属性,它是一个枚举值,代表错误的类型。

  1. 组织错误

一个很好的方法是创建一个静态类来组织预期的错误。例如:

class DivisionErrors {
  static Errors cannotdivideByZero = Errors.unexpected(
      code: "Division.CannotdivideByZero",
      description: "Cannot divide by zero.");
}

然后可以像这样使用:

public ErrorOr&lt;double&gt; divide(int a, int b) {
  if (b == 0 {
    return DivisionErrors.cannotdivideByZero;
  }

  return a / b;
}

更多关于Flutter错误处理或增强插件error_or_plus的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter错误处理或增强插件error_or_plus的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


在Flutter中处理错误或增强错误处理体验时,error_or_plus 插件(假设这是一个假想的插件名称,因为 Flutter 官方并没有直接名为 error_or_plus 的插件)可以用来简化错误捕获、处理和报告。虽然这个插件是虚构的,但我可以展示一个类似的错误处理机制,并给出一些示例代码来展示如何在 Flutter 应用中实现增强型错误处理。

通常,在 Flutter 中处理错误时,你可能会使用 Dart 的 try-catch 语句,或者结合自定义的错误处理逻辑和第三方库(如 Sentry、Firebase Crashlytics 等)来捕获和报告错误。

以下是一个简化的示例,展示如何在 Flutter 应用中处理错误,并假设我们有一个自定义的 ErrorHandler 类来增强错误处理功能:

1. 创建 ErrorHandler

首先,我们创建一个 ErrorHandler 类,用于集中处理应用中的错误。

import 'dart:async';

class ErrorHandler {
  static final ErrorHandler _instance = ErrorHandler._init();
  bool isInDebugMode = false;

  // Private constructor prevents instantiation from other classes.
  ErrorHandler._init() {
    isInDebugMode = !kReleaseMode;
  }

  factory ErrorHandler() {
    return _instance;
  }

  // Function to handle errors globally.
  Future<void> handleError(Object error, StackTrace? stackTrace) async {
    // Log the error to the console.
    print("Error: $error");
    if (stackTrace != null) {
      print("Stack Trace: $stackTrace");
    }

    // Optionally, send the error to a remote logging service.
    // For example, using Firebase Crashlytics or Sentry.
    // await FirebaseCrashlytics.getInstance().recordError(error, stackTrace);
    // or
    // await Sentry.captureException(error, stackTrace: stackTrace);

    // Show a snackbar or dialog to the user indicating an error occurred.
    // This can be done using a global key for ScaffoldMessenger.
    // Here, we'll just print a message to simulate this.
    print("An unexpected error occurred. Please try again later.");
  }
}

2. 使用 ErrorHandler 捕获错误

然后,我们可以在应用中的关键位置使用 ErrorHandler 来捕获和处理错误。

import 'package:flutter/material.dart';
import 'error_handler.dart'; // Assume our ErrorHandler class is in this file.

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Error Handling Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: HomeScreen(),
    );
  }
}

class HomeScreen extends StatefulWidget {
  @override
  _HomeScreenState createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  final ErrorHandler errorHandler = ErrorHandler();

  void performRiskyOperation() async {
    try {
      // Simulate a risky operation that might throw an error.
      throw Exception("Something went wrong!");
    } catch (error, stackTrace) {
      // Handle the error using our custom ErrorHandler.
      await errorHandler.handleError(error, stackTrace);
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Error Handling Demo'),
      ),
      body: Center(
        child: ElevatedButton(
          onPressed: performRiskyOperation,
          child: Text('Perform Risky Operation'),
        ),
      ),
    );
  }
}

3. 扩展错误处理(可选)

根据需求,你可以进一步扩展 ErrorHandler 类,比如添加不同类型的错误处理逻辑、将错误报告到远程服务器、或者显示不同类型的用户通知。

这个示例展示了如何在 Flutter 应用中创建一个基本的错误处理机制。虽然 error_or_plus 插件是虚构的,但你可以使用类似的方法结合其他第三方库(如 Sentry、Firebase Crashlytics)来实现更强大的错误处理和报告功能。

回到顶部