Flutter结果处理插件result_kt的使用

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

Flutter结果处理插件result_kt的使用

Result Kt

pub License: MIT result_kt codecov

这是一个Dart包,它提供了与Kotlin中的Result类型和runCatching函数相似的功能。你也可以将其与Stream一起使用。

为什么选择这个包?

我需要一个类似于Kotlin中实现的东西,并且不想添加其他在我的项目中不会用到的功能。虽然还有一个类似的包result,但它已经被废弃了。

使用方法

在你的pubspec.yaml文件中添加依赖:

dependencies:
  result_kt:

然后在你想使用它的文件中导入它,例如主文件:

import 'package:result_kt/result_kt.dart';

概览

Result

你可以用成功的结果值或失败的错误和堆栈信息来封装结果。它类似于你在其他包(如dartzfpdart等)中看到的Either类型。

可用的方法包括:

  • isSuccess
  • isFailure
  • getOrNull
  • failureOrNull
  • getOrThrow
  • getOrDefault
  • getOrElse
  • onSuccess
  • onFailure
  • fold
  • map
  • mapCatching
  • recover
  • recoverCatching

更多API文档请参阅官方文档

示例代码:

Result.success(0)
    .onSuccess(
        action: print,
    )
    .onFailure(
    action: (failure) => print(
            failure.error.toString(),
        ),
    );

Result<int>.failure(Exception(), StackTrace.current)
    .onSuccess(
        action: print,
    )
    .onFailure(
        action: (failure) => print(
            failure.error.toString(),
        ),
    );

runCatching

执行传入的函数并捕获任何抛出的错误。如果调用成功,则返回封装在Result中的值;否则,返回封装在Result中的错误和堆栈信息。

示例代码:

final result = runCatching(() => 1);
result
    .onSuccess(
        action: print,
    )
    .onFailure(
        action: (failure) => print(
            failure.error.toString(),
        ),
    );

注意:你可以指定想要捕获的错误类型,如果匹配,则返回Result,否则重新抛出错误。

final result = runCatching<int>(
    () => throw 'exception',
    test: (error) => error is Exception,
),
// `onFailure` never called
result
    .onFailure(
        action: (failure) => print(
            failure.error.toString(),
        ),
    );

Stream

将流值转换为结果。

示例代码:

final streamController = StreamController<int>();
final resultStream = streamController.stream.toResult();
resultStream.listen(print); // Success(0)
streamController.add(0);

runCatching一样,你可以指定想要转换的错误类型,如果匹配,则返回Result;否则,使用EventSink.addError添加错误和堆栈信息。

final streamController = StreamController<int>();
final resultStream = streamController.stream.toResult(
    test: (error) => error is Exception,
);
resultStream.listen(print); // Failure(error: Exception, stackTrace: null)
streamController.addError(Exception());

其他类似包

  • dartz: 提供了许多函数式编程辅助工具,包括类似于ResultEither类型。
  • fpdart: 类似于dartz,但文档更好。
  • either_option: 包含EitherOption,支持所有典型的函数式操作。
  • result: 提供了一些基本操作,可能适用于简单的情况(此包已有两年未更新)。
  • rust_like_result: 提供了一个类似于Rust中的简单Result类型。
  • simple_result: 基于Swift中同名类型的Result
  • oxidized: 提供了类似于Rust中的类型,如表示值或错误的Result和包含某些值或无值的Option

维护者和支持

如果你喜欢这个包,请给它一个⭐️。如果你想帮助的话,可以:

  • Fork这个仓库
  • 发送带有新功能的Pull Request
  • 分享这个包
  • 如果发现bug或有新的扩展建议,请创建issue

Pull Request标题应遵循Conventional Commits规范。

许可证

版权所有 © 2022 Kauê Martins
本项目采用MIT许可证。

示例Demo

下面是一个完整的示例,展示了如何使用result_kt进行输入验证:

// ignore_for_file: avoid_print
import 'dart:io';

import 'package:result_kt/result_kt.dart';

void main() {
  stdout.writeln('请输入一个邮箱地址:');
  final email = stdin.readLineSync()!;
  final result = runCatching(() => validateEmailAddress(email));
  result
      .onSuccess(action: print)
      .onFailure(action: (value) => print(value.error.toString()));
}

String validateEmailAddress(String email) {
  const emailRegex =
      r"""^[a-zA-Z0-9.a-zA-Z0-9.!#$%&'*+-/=?^_`{|}~]+@[a-zA-Z0-9]+\.[a-zA-Z]+""";
  if (RegExp(emailRegex).hasMatch(email)) {
    return '$email 是一个有效的邮箱地址';
  } else {
    throw FormatException('$email 不是一个有效的邮箱地址');
  }
}

在这个例子中,我们通过命令行提示用户输入一个邮箱地址,然后使用runCatching来捕获可能的异常,并根据结果输出相应的信息。


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

1 回复

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


当然,result_kt 是一个用于在 Flutter 中处理结果的插件,特别是在与原生代码(如 Kotlin 或 Swift)交互时非常有用。以下是如何在 Flutter 项目中使用 result_kt 插件的一个简单示例。

1. 添加依赖

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

dependencies:
  flutter:
    sdk: flutter
  result_kt: ^最新版本号  # 请替换为实际的最新版本号

然后运行 flutter pub get 以获取依赖。

2. 原生代码集成(Kotlin 示例)

在 Android 的原生代码中,你可能需要处理一些异步任务并返回结果。这里是一个简单的 Kotlin 示例,展示如何通过 result_kt 插件将结果传递回 Flutter。

MainActivity.kt 中:

package com.example.yourapp

import androidx.annotation.NonNull
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugins.GeneratedPluginRegistrant
import com.github.nikolaymenzhulin.resultkt.*

class MainActivity: FlutterActivity() {
    private val CHANNEL = "com.example.yourapp/channel"

    override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)
        GeneratedPluginRegistrant.registerWith(flutterEngine)

        MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler { call, result ->
            if (call.method == "fetchData") {
                fetchData().onSuccess { data ->
                    result.success(data)
                }.onFailure { error ->
                    result.error("ERROR", error.message ?: "Unknown error", null)
                }
            } else {
                result.notImplemented()
            }
        }
    }

    private fun fetchData(): Result<String, Exception> {
        // 模拟一个异步数据获取任务
        return try {
            delay(1000) // 模拟延迟
            "Data fetched successfully!".success()
        } catch (e: Exception) {
            e.failure()
        }
    }

    // 注意:这里的 delay 是一个模拟函数,实际使用中你需要替换为真实的异步操作,例如网络请求。
    // 由于 Kotlin 标准库中没有直接的 delay 函数,这里仅作为示例。在实际项目中,你可以使用协程或线程来实现延迟。
}

注意:上面的 delay 函数是一个假设的模拟函数,用于展示延迟效果。在实际项目中,你需要使用 Kotlin 协程或线程来实现异步操作。

3. Flutter 代码

在 Flutter 端,你需要创建一个与原生代码交互的通道,并调用原生方法。

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:result_kt/result_kt.dart'; // 假设 result_kt 提供了 Dart 端的 Result 类型(实际可能不需要,这里仅为假设)

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

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  String _result = '';

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

  Future<void> _fetchData() async {
    try {
      final String result = await _platform.invokeMethod('fetchData');
      setState(() {
        _result = result;
      });
    } on PlatformException catch (e) {
      setState(() {
        _result = "Failed to fetch data: '${e.message}'.";
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Flutter Result Handling'),
        ),
        body: Center(
          child: Text(_result),
        ),
      ),
    );
  }
}

class _Platform {
  MethodChannel _channel = const MethodChannel('com.example.yourapp/channel');

  Future<String> invokeMethod(String method) async {
    try {
      final String result = await _channel.invokeMethod(method);
      return result;
    } on PlatformException catch (e) {
      throw e;
    }
  }
}

final _platform = _Platform();

总结

上述代码展示了如何在 Flutter 中使用 result_kt 插件来处理与原生代码交互的结果。请注意,result_kt 主要是 Kotlin 库,用于原生端的 Result 类型处理,而 Flutter 端通常使用 Dart 的异步处理机制(如 Futureasync/await)。如果 result_kt 提供了 Dart 端的绑定或扩展,你可以根据具体文档进行集成。如果没有,你可以像上面示例那样,使用 Dart 的标准异步处理模式。

此外,由于 result_kt 可能不是一个广泛认知的 Flutter 插件,具体的使用细节和 API 可能需要参考其官方文档或源代码。

回到顶部