写点什么

在 Flutter 和 Dart 中取消 Future 的 3 种方法

作者:坚果
  • 2022 年 4 月 05 日
  • 本文字数:2617 字

    阅读完需:约 9 分钟

作者:坚果

公众号:"大前端之旅"

华为云享专家,InfoQ 签约作者,阿里云专家博主,51CTO 博客首席体验官,开源项目GVA成员之一,专注于大前端技术的分享,包括 Flutter,小程序,安卓,VUE,JavaScript。


本文将引导您了解在 Flutter 和 Dart 中取消 future 的 3 种不同方法。

使用异步包(推荐)

async包由 Dart 编程语言的作者开发和发布。它提供了 dart:async 风格的实用程序来增强异步计算。可以帮助我们取消 Future 的是**CancelableOperation**类:


var myCancelableFuture = CancelableOperation.fromFuture(  Future<T> inner,   { FutureOr onCancel()? })
// call the cancel() method to cancel the futuremyCancelableFuture.cancel();
复制代码


为了更清楚,请参阅下面的实际示例。

完整示例

应用预览


我们要构建的应用程序有一个浮动按钮。按下此按钮时,将开始异步操作(这需要 5 秒才能完成)。按钮的背景从靛蓝变为红色,其标签从“开始”变为“取消”,现在您可以使用它来取消 Future。


  • 如果您在 Future 完成前 5 秒内点击取消按钮,屏幕将显示“Future 已被取消”。

  • 如果您什么都不做,则 5 秒后屏幕将显示“Future completed”。


一个演示价值超过一千字:

代码

1.通过执行以下操作安装异步包:


flutter pub add async
复制代码


然后运行:


flutter pub get
复制代码


2.main.dart 中的完整源代码(附解释):


// main.dartimport 'package:flutter/material.dart';import 'package:async/async.dart';
void main() { runApp(const MyApp());}
class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return MaterialApp( // Remove the debug banner debugShowCheckedModeBanner: false, title: '大前端之旅', theme: ThemeData( primarySwatch: Colors.indigo, ), home: const HomePage()); }}
class HomePage extends StatefulWidget { const HomePage({Key? key}) : super(key: key);
@override _HomePageState createState() => _HomePageState();}
class _HomePageState extends State<HomePage> { // this future will return some text once it completes Future<String?> _myFuture() async { await Future.delayed(const Duration(seconds: 5)); return 'Future completed'; }
// keep a reference to CancelableOperation CancelableOperation? _myCancelableFuture;
// This is the result returned by the future String? _text;
// Help you know whether the app is "loading" or not bool _isLoading = false;
// This function is called when the "start" button is pressed void _getData() async { setState(() { _isLoading = true; });
_myCancelableFuture = CancelableOperation.fromFuture( _myFuture(), onCancel: () => 'Future has been canceld', ); final value = await _myCancelableFuture?.value;
// update the UI setState(() { _text = value; _isLoading = false; }); }
// this function is called when the "cancel" button is tapped void _cancelFuture() async { final result = await _myCancelableFuture?.cancel(); setState(() { _text = result; _isLoading = false; }); }
@override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('大前端之旅')), body: Center( child: _isLoading ? const CircularProgressIndicator() : Text( _text ?? 'Press Start Button', style: const TextStyle(fontSize: 28), ), ), // This button is used to trigger _getDate() and _cancelFuture() functions // the function is called depends on the _isLoading variable floatingActionButton: ElevatedButton( onPressed: () => _isLoading ? _cancelFuture() : _getData(), child: Text(_isLoading ? 'Cancel' : 'Start'), style: ElevatedButton.styleFrom( padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 30), primary: _isLoading ? Colors.red : Colors.indigo), ), ); }}
复制代码

使用 timeout() 方法

这种方法既快速又简单。但是,它不是很灵活。


使用timeout()方法,您可以限制 Future 的时间(例如 3 秒)。如果 future 及时完成,它的值将被返回。另一方面,如果 Future 超过限制时间,将执行 onTimeout 函数:


Future<T> timeout(   Duration timeLimit,  {FutureOr<T> onTimeout()?})
复制代码

快速示例

创建一个虚拟的 Future:


Future<String?> _myFuture() async {    await Future.delayed(const Duration(seconds: 10));    return 'Future completed';}
复制代码


设置超时 3 秒:


_myFuture().timeout(      const Duration(seconds: 3),      onTimeout: () =>          'The process took too much time to finish. Please try again later',);
复制代码

将 Future 转换为流

您可以使用 Future 类的asStream()方法来创建一个包含原始 Future 结果的流。现在您可以取消对该流的订阅。

快速示例

// don't forget to import thisimport 'dart:async';
// Create a demo futureFuture<dynamic> _loadData() async { await Future.delayed(const Duration(seconds: 10)); return 'Some Data';}
// a reference to the stream subscription// so that we can call _sub.cancel() laterStreamSubscription<dynamic>? _sub;
// convert the future to a stream_sub = _loadData().asStream().listen((data) { // do something with "data" print(data); });
// cancel the stream subscription_sub.cancel();
复制代码


请注意,这个快速示例仅简要描述了事物的工作原理。您必须对其进行修改以使其可在现有项目中运行。

结论

你已经学会了不止一种方法来取消 Flutter 中的 Future。从其中选择一个以在您的应用程序中实现,以使其在处理异步任务时更加健壮和吸引人。

发布于: 2022 年 04 月 05 日阅读数: 17
用户头像

坚果

关注

此间若无火炬,我便是唯一的光 2020.10.25 加入

公众号:“大前端之旅”,华为云享专家,InfoQ签约作者,51CTO博客首席体验官,专注于大前端技术的分享,包括Flutter,小程序,安卓,VUE,JavaScript。

评论

发布
暂无评论
在 Flutter 和 Dart 中取消 Future 的 3 种方法_4月日更_坚果_InfoQ写作平台