详解Flutter和Dart取消Future的三种方法
作者:大前端之旅 发布时间:2022-10-15 12:44:16
使用异步包(推荐)
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();
为了更清楚,请参阅下面的实际示例。
完整示例
应用预览
我们要构建的应用程序有一个浮动按钮。按下此按钮时,将开始异步操作(这需要 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。从其中选择一个以在您的应用程序中实现,以使其在处理异步任务时更加健壮和吸引人。
来源:https://juejin.cn/post/7083506236112502814
猜你喜欢
- 写在前面注:本文章使用的 SpringBoot 版本为 2.2.4.RELEASE,其 Spring 版本为 5.2.3.RELEASE前言
- 一、C# Thread类的基本用法通过System.Threading.Thread类可以开始新的线程,并在线程堆栈中运行静态或实例方法。可
- 适合人群学完Java基础想通过Java快速构建web应用程序想学习或了解SpringBoot背景本节给大家讲讲 Java的Spri
- 需求分析需求一:图片列表查询,从后台返回数据,将数据展示在页面上需求二:新增图片,将新增图书的数据传递到后台,并在控制台打印说明:此次案例的
- 我们经常在项目中使用的线程池,但是是否关心过线程池的关闭呢,可能很多时候直接再项目中直接创建线程池让它一直运行当任务执行结束不在需要了也不去
- 第一次接触到随机数还是在c语言里面 使用的是 rand(); 但是重新执行一次的时候会发现,诶,居然和上一次执行的结果是一样的,因为没有初始
- [LeetCode] 131.Palindrome Partitioning 拆分回文串Given a string s, par
- ImageView是用于界面上显示图片的控件。属性1、为ImageView设置图片①android:src="@drawable/
- LongAdder实现原理图高并发下N多线程同时去操作一个变量会造成大量线程CAS失败,然后处于自旋状态,导致严重浪费CPU资源,降低了并发
- 一、前期准备表CREATE TABLE `school_student` ( `id` int(11) NOT NULL AUT
- redis redisson 集合操作相关类及接口Rlist:链表public interface RList<V> exten
- 本文实例讲述了Android获取apk签名指纹的md5值以防止重新被打包的实现方法。分享给大家供大家参考,具体如下:做个记录(这里只是Jav
- 这篇文章主要介绍了如何通过SpringBoot实现商城秒杀系统,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,
- 本文实例讲述了C#中const用法。分享给大家供大家参考。具体用法分析如下:const是一个c语言的关键字,它限定一个变量不允许被改变。使用
- 本章先讲解Java随机数的几种产生方式,然后通过示例对其进行演示。广义上讲,Java中的随机数的有三种产生方式:(01). 通过System
- 本文实例为大家分享了C#支付宝新版支付请求接口调用的具体代码,供大家参考,具体内容如下因为支付宝已经集成了完整的SDK,所以可以使用SDK直
- 一、校验分类数据的校验一般分为**前端校验、后端校验**二、前端校验前端校验是最为明显的,先说一下:① HTML非空校验 如 HTML5 新
- 1、下载SpringMVC框架架包,下载地址: 点击下载 点击打开地址如图所示,点击下载即可 然后把相关的jar复制到lib下导
- 导入依赖(pom.xml) <!--整合Shiro安全框架--> <dependency>
- 一、Android Studio 主题的设置1.1 设置Android Studio 自带的主题及包名字体大小1.2 导入第三方主题:下载了