Flutter条件逻辑处理插件either_dart的使用

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

Flutter条件逻辑处理插件either_dart的使用

介绍

either_dart 是一个用于错误处理和铁路导向编程(Railway Oriented Programming)的库。它支持异步 mapthen 操作,简化了与异步计算 Future<Either> 的工作。

build status

安装

pubspec.yaml 文件中添加依赖:

dependencies:
  either_dart: ^latest_version # 替换为最新版本号

文档

使用方法

基本用法

创建自定义错误类型

首先,创建两个实体类来表示可能的错误和成功的结果:

enum AppError {
  NotFound,
  BadRequest,
  ServerError,
  BadResponse,
  JsonParsing,
}

class MyError {
  final AppError key;
  final String? message;

  const MyError({
    required this.key, 
    this.message,
  });
}

使用 Either 类型

可以使用 Either 来返回成功或失败的结果:

Either<MyError, String> getCityNameByCode(int code) {
  const cities = <int, String>{
    1: 'New York',
    2: 'Los Angeles',
    // 其他城市代码
  };

  if (cities.containsKey(code)) {
    return Right(cities[code]!);
  } else {
    return Left(
      MyError(
        key: AppError.NotFound, 
        message: '[getCityNameByCode] can`t convert code:$code to city name',
      ),
    );
  }
}

也可以使用 Either.condLazy 方法来简化条件判断:

return Either.condLazy(
  cities.containsKey(code), 
  () => cities[code]!, 
  () => MyError(
    key: AppError.NotFound, 
    message: '[getCityNameByCode] can`t convert code:$code to city name',
  ),
);

高级用法

异步操作

either_dart 提供了 FutureEither 扩展,用于处理异步计算。以下是一个从服务器获取数据并处理响应的例子:

import 'package:either_dart/either.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';

Future<Either<AppError, http.Response>> safe(Future<http.Response> request) async {
  try {
    return Right(await request);
  } catch (e) {
    return Left(MyError(
        key: AppError.BadRequest,
        message: "Request executing with errors:$e"));
  }
}

Either<AppError, http.Response> checkHttpStatus(http.Response response) {
  if (response.statusCode == 200)
    return Right(response);
  if (response.statusCode >= 500)
    return Left(MyError(
        key: AppError.ServerError,
        message: "Server error with http status ${response.statusCode}"));
  return Left(MyError(
      key: AppError.BadResponse,
      message: "Bad http status ${response.statusCode}"));
}

Future<Either<AppError, dynamic>> parseJson(http.Response response) async {
  try {
    return Right(json.decode(response.body));
  } catch (e) {
    return Left(MyError(
      key: AppError.JsonParsing, 
      message: 'failed on json parsing'));
  }
}

Future<Either<AppError, Data>> getDataFromServer() {
  return 
    safe(http.get(Uri.parse('some uri')))
      .thenRight(checkHttpStatus)
      .thenRight(parseJson) 
      .mapRight(Data.fromJson);
}

示例代码

以下是一个完整的Flutter应用程序示例,展示了如何使用 either_dart 处理来自服务器的数据:

import 'package:either_dart/either.dart';
import 'package:flutter/material.dart';

class Data {
  final String data;
  Data(this.data);
}

class ServerError {
  final String message;
  ServerError(this.message);
}

class Client {
  bool firstRequest = true;

  Future<Either<ServerError, Data>> getDataFromServer() async {
    await Future.delayed(const Duration(seconds: 2));
    if (!firstRequest) {
      return Right(Data("other string"));
    } else {
      firstRequest = false;
      return Left(ServerError("loss connection"));
    }
  }
}

class WidgetReceivingData extends StatefulWidget {
  @override
  createState() => _WidgetReceivingDataState();
}

class _WidgetReceivingDataState extends State<WidgetReceivingData> {
  final Client apiClient = Client();
  Future<Either<ServerError, Data>>? _load;

  @override
  void initState() {
    super.initState();
    _load = apiClient.getDataFromServer();
  }

  void reloadServerData() {
    setState(() {
      _load = apiClient.getDataFromServer();
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: FutureBuilder<Either<ServerError, Data>>(
            future: _load,
            builder: (context, snapshot) {
              return Center(
                  child: snapshot.hasData && 
                          snapshot.connectionState != ConnectionState.waiting
                      ? snapshot.data!.fold<Widget>(
                          (err) => ServerErrorWidget(err, onReload: reloadServerData),
                          (data) => DataWidget(data))
                      : CircularProgressIndicator());
            }));
  }
}

class DataWidget extends StatelessWidget {
  final Data _data;
  const DataWidget(this._data);

  @override
  Widget build(BuildContext context) {
    return Text("Data: ${_data.data}");
  }
}

class ServerErrorWidget extends StatelessWidget {
  final ServerError _error;
  final VoidCallback onReload;
  const ServerErrorWidget(this._error, {required this.onReload});

  @override
  Widget build(BuildContext context) {
    return Column(mainAxisAlignment: MainAxisAlignment.center, children: [
      Text("Error: ${_error.message}"),
      SizedBox(height: 20),
      ElevatedButton(
        onPressed: onReload,
        child: Text("Try reload"),
      )
    ]);
  }
}

void main() => runApp(MaterialApp(
      home: WidgetReceivingData(),
      theme: ThemeData(
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
    ));

总结

either_dart 提供了一种简洁且强大的方式来处理同步和异步条件逻辑,特别适用于需要优雅处理错误和异常的场景。通过结合Flutter的UI框架,可以构建出更加健壮和用户友好的应用程序。


更多关于Flutter条件逻辑处理插件either_dart的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter条件逻辑处理插件either_dart的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


在Flutter中,either_dart 是一个用于处理条件逻辑的插件,它提供了一种优雅的方式来处理可能产生多种结果的操作,比如成功或失败的情况。这种处理方式类似于 Rust 语言中的 Result 类型或者 Swift 中的 Result<Success, Failure> 类型。

以下是一个使用 either_dart 的简单示例,展示了如何在 Flutter 应用中进行条件逻辑处理。

首先,你需要在你的 pubspec.yaml 文件中添加 either_dart 依赖:

dependencies:
  flutter:
    sdk: flutter
  either_dart: ^2.0.0  # 确保版本号是最新的

然后,运行 flutter pub get 来安装依赖。

接下来,我们来看一个具体的代码示例。假设我们有一个函数,它尝试从网络获取数据,并返回一个 Either 类型的结果,这个结果可能是成功的数据,也可能是错误信息。

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

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Either Dart Example'),
        ),
        body: Center(
          child: FutureBuilder<Either<String, String>>(
            future: fetchData(),
            builder: (context, snapshot) {
              if (snapshot.connectionState == ConnectionState.waiting) {
                return CircularProgressIndicator();
              } else if (snapshot.hasError) {
                return Text('Error: ${snapshot.error}');
              } else {
                return EitherWidget(either: snapshot.data!);
              }
            },
          ),
        ),
      ),
    );
  }
}

// 模拟一个从网络获取数据的函数
Future<Either<String, String>> fetchData() async {
  // 模拟延迟
  await Future.delayed(Duration(seconds: 2));

  // 这里我们假设获取数据成功
  // 你可以根据实际需求修改为返回 Left(error) 来模拟失败
  return Right('Data fetched successfully!');
  // return Left('Failed to fetch data');
}

class EitherWidget extends StatelessWidget {
  final Either<String, String> either;

  EitherWidget({required this.either});

  @override
  Widget build(BuildContext context) {
    return either.fold(
      (error) => Text('Error: $error'),
      (data) => Text('Success: $data'),
    );
  }
}

在这个示例中:

  1. 我们定义了一个 fetchData 函数,它模拟从网络获取数据。这个函数返回一个 Future<Either<String, String>> 类型的值,其中 Left 表示错误,Right 表示成功的数据。
  2. MyApp 中,我们使用 FutureBuilder 来处理异步操作。当数据正在加载时,显示一个 CircularProgressIndicator;如果发生错误,显示错误信息;否则,显示 EitherWidget
  3. EitherWidget 使用 either.fold 方法来根据 Either 的类型(LeftRight)显示不同的内容。如果是 Left,显示错误信息;如果是 Right,显示成功的数据。

通过这种方式,你可以在你的 Flutter 应用中优雅地处理条件逻辑。

回到顶部