详解Flutter和Dart取消Future的三种方法


Posted in Java/Android onApril 07, 2022

使用异步包(推荐)

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

var myCancelableFuture = CancelableOperation.fromFuture(
  Future<T> inner, 
  { FutureOr onCancel()? }
)
​
// call the cancel() method to cancel the future
myCancelableFuture.cancel();

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

完整示例

应用预览

详解Flutter和Dart取消Future的三种方法

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

  • 如果您在Future完成前 5 秒内点击取消按钮,屏幕将显示“Future已被取消”。
  • 如果您什么都不做,则 5 秒后屏幕将显示“Future completed”。

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

代码

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

flutter pub add async

然后运行:

flutter pub get

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

// main.dart
import '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 this
import 'dart:async';
​
// Create a demo future
Future<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() later
StreamSubscription<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。从其中选择一个以在您的应用程序中实现,以使其在处理异步任务时更加健壮和吸引人。

以上就是详解Flutter和Dart取消Future的三种方法的详细内容,更多关于Flutter Dart取消Future的资料请关注三水点靠木其它相关文章!

Java/Android 相关文章推荐
如何解决springcloud feign 首次调用100%失败的问题
Jun 23 Java/Android
springboot集成flyway自动创表的详细配置
Jun 26 Java/Android
浅谈自定义校验注解ConstraintValidator
Jun 30 Java/Android
Java Kafka 消费积压监控的示例代码
Jul 01 Java/Android
Java数据开发辅助工具Docker与普通程序使用方法
Sep 15 Java/Android
springboot如何接收application/x-www-form-urlencoded类型的请求
Nov 02 Java/Android
OpenCV实现普通阈值
Nov 17 Java/Android
Netty客户端接入流程NioSocketChannel创建解析
Mar 25 Java/Android
Android开发 使用文件储存的方式保存QQ密码
Apr 24 Java/Android
Java 死锁解决方案
May 11 Java/Android
springboot读取nacos配置文件
May 20 Java/Android
阿里面试Nacos配置中心交互模型是push还是pull原理解析
Jul 23 Java/Android
java如何实现获取客户端ip地址的示例代码
Apr 07 #Java/Android
Android Flutter实现3D动画效果示例详解
Apr 07 #Java/Android
Android Flutter实现图片滑动切换效果
MyBatis配置文件解析与MyBatis实例演示
Java 深入探究讲解简单工厂模式
springboot用户数据修改的详细实现
Apr 06 #Java/Android
Java中API的使用方法详情
You might like
js和php邮箱地址验证的实现方法
2014/01/09 PHP
PHP+JQuery+Ajax实现分页方法详解
2016/08/06 PHP
PHP常量及变量区别原理详解
2020/08/14 PHP
js解析与序列化json数据(三)json的解析探讨
2013/02/01 Javascript
用js实现trim()的解决办法
2013/04/16 Javascript
window.location.href IE下跳转失效的解决方法
2014/03/27 Javascript
AngularJS + Node.js + MongoDB开发的基于高德地图位置的通讯录
2015/01/02 Javascript
javascript实现删除前弹出确认框
2015/06/04 Javascript
jQuery实现背景弹性滚动的导航效果
2016/06/01 Javascript
使用Angular.js实现简单的购物车功能
2016/11/21 Javascript
JavaScript实现垂直向上无缝滚动特效代码
2016/11/23 Javascript
JQuery实现动态操作表格
2017/01/11 Javascript
微信小程序 支付后台java实现实例
2017/05/09 Javascript
ExtJs异步无法向外传值和赋值的完美解决办法
2017/06/14 Javascript
Vant的安装和配合引入Vue.js项目里的方法步骤
2018/12/05 Javascript
python抓取网页内容示例分享
2014/02/24 Python
Python抓取京东图书评论数据
2014/08/31 Python
python3+PyQt5+Qt Designer实现堆叠窗口部件
2018/04/20 Python
Python实现确认字符串是否包含指定字符串的实例
2018/05/02 Python
浅谈python中拼接路径os.path.join斜杠的问题
2018/10/23 Python
python fuzzywuzzy模块模糊字符串匹配详细用法
2019/08/29 Python
Django 设置多环境配置文件载入问题
2020/02/25 Python
keras Lambda自定义层实现数据的切片方式,Lambda传参数
2020/06/11 Python
Python Request类源码实现方法及原理解析
2020/08/17 Python
HTML5实现页面切换激活的PageVisibility API使用初探
2016/05/13 HTML / CSS
狗狗玩具、零食和咀嚼物的月度送货服务:Super Chewer
2018/08/22 全球购物
飞利浦法国官网:Philips法国
2019/07/10 全球购物
Java里面如何创建一个内部类的实例
2015/01/19 面试题
财务会计毕业生自荐信
2013/11/02 职场文书
社区敬老月活动实施方案
2014/02/17 职场文书
怎么写好自荐书
2014/03/02 职场文书
2014镇党委书记党建工作汇报材料
2014/11/02 职场文书
民事申诉状范本
2015/05/20 职场文书
浙江省杭州市平均工资标准是多少?
2019/07/09 职场文书
用Python制作灯光秀短视频的思路详解
2021/04/13 Python
基于PyTorch实现一个简单的CNN图像分类器
2021/05/29 Python