经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 移动开发 » Flutter » 查看文章
详解Flutter和Dart取消Future的三种方法
来源:jb51  时间:2022/4/7 10:49:20  对本文有异议

使用异步包(推荐)

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

  1. var myCancelableFuture = CancelableOperation.fromFuture(
  2. Future<T> inner,
  3. { FutureOr onCancel()? }
  4. )
  5. ?
  6. // call the cancel() method to cancel the future
  7. myCancelableFuture.cancel();

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

完整示例

应用预览

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

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

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

代码

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

  1. flutter pub add async

然后运行:

  1. flutter pub get

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

  1. // main.dart
  2. import 'package:flutter/material.dart';
  3. import 'package:async/async.dart';
  4. ?
  5. void main() {
  6. runApp(const MyApp());
  7. }
  8. ?
  9. class MyApp extends StatelessWidget {
  10. const MyApp({Key? key}) : super(key: key);
  11. @override
  12. Widget build(BuildContext context) {
  13. return MaterialApp(
  14. // Remove the debug banner
  15. debugShowCheckedModeBanner: false,
  16. title: '大前端之旅',
  17. theme: ThemeData(
  18. primarySwatch: Colors.indigo,
  19. ),
  20. home: const HomePage());
  21. }
  22. }
  23. ?
  24. class HomePage extends StatefulWidget {
  25. const HomePage({Key? key}) : super(key: key);
  26. ?
  27. @override
  28. _HomePageState createState() => _HomePageState();
  29. }
  30. ?
  31. class _HomePageState extends State<HomePage> {
  32. // this future will return some text once it completes
  33. Future<String?> _myFuture() async {
  34. await Future.delayed(const Duration(seconds: 5));
  35. return 'Future completed';
  36. }
  37. ?
  38. // keep a reference to CancelableOperation
  39. CancelableOperation? _myCancelableFuture;
  40. ?
  41. // This is the result returned by the future
  42. String? _text;
  43. ?
  44. // Help you know whether the app is "loading" or not
  45. bool _isLoading = false;
  46. ?
  47. // This function is called when the "start" button is pressed
  48. void _getData() async {
  49. setState(() {
  50. _isLoading = true;
  51. });
  52. ?
  53. _myCancelableFuture = CancelableOperation.fromFuture(
  54. _myFuture(),
  55. onCancel: () => 'Future has been canceld',
  56. );
  57. final value = await _myCancelableFuture?.value;
  58. ?
  59. // update the UI
  60. setState(() {
  61. _text = value;
  62. _isLoading = false;
  63. });
  64. }
  65. ?
  66. // this function is called when the "cancel" button is tapped
  67. void _cancelFuture() async {
  68. final result = await _myCancelableFuture?.cancel();
  69. setState(() {
  70. _text = result;
  71. _isLoading = false;
  72. });
  73. }
  74. ?
  75. @override
  76. Widget build(BuildContext context) {
  77. return Scaffold(
  78. appBar: AppBar(title: const Text('大前端之旅')),
  79. body: Center(
  80. child: _isLoading
  81. ? const CircularProgressIndicator()
  82. : Text(
  83. _text ?? 'Press Start Button',
  84. style: const TextStyle(fontSize: 28),
  85. ),
  86. ),
  87. // This button is used to trigger _getDate() and _cancelFuture() functions
  88. // the function is called depends on the _isLoading variable
  89. floatingActionButton: ElevatedButton(
  90. onPressed: () => _isLoading ? _cancelFuture() : _getData(),
  91. child: Text(_isLoading ? 'Cancel' : 'Start'),
  92. style: ElevatedButton.styleFrom(
  93. padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 30),
  94. primary: _isLoading ? Colors.red : Colors.indigo),
  95. ),
  96. );
  97. }
  98. }

使用 timeout() 方法

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

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

  1. Future<T> timeout(
  2. Duration timeLimit,
  3. {FutureOr<T> onTimeout()?}
  4. )

快速示例

创建一个虚拟的Future:

  1. Future<String?> _myFuture() async {
  2. await Future.delayed(const Duration(seconds: 10));
  3. return 'Future completed';
  4. }

设置超时 3 秒:

  1. _myFuture().timeout(
  2. const Duration(seconds: 3),
  3. onTimeout: () =>
  4. 'The process took too much time to finish. Please try again later',
  5. );

将Future转换为流

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

快速示例

  1. // don't forget to import this
  2. import 'dart:async';
  3. ?
  4. // Create a demo future
  5. Future<dynamic> _loadData() async {
  6. await Future.delayed(const Duration(seconds: 10));
  7. return 'Some Data';
  8. }
  9. ?
  10. // a reference to the stream subscription
  11. // so that we can call _sub.cancel() later
  12. StreamSubscription<dynamic>? _sub;
  13. ?
  14. // convert the future to a stream
  15. _sub = _loadData().asStream().listen((data) {
  16. // do something with "data"
  17. print(data);
  18. });
  19. ?
  20. // cancel the stream subscription
  21. _sub.cancel();

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

结论

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

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

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号