软件编程
位置:首页>> 软件编程>> Android编程>> 详解Flutter和Dart取消Future的三种方法

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

作者:大前端之旅  发布时间:2022-10-15 12:44:16 

标签:Flutter,Dart,Future

使用异步包(推荐)

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 秒才能完成)。按钮的背景从靛蓝变为红色,其标签从&ldquo;开始&rdquo;变为&ldquo;取消&rdquo;,现在您可以使用它来取消Future。

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

  • 如果您什么都不做,则 5 秒后屏幕将显示&ldquo;Future completed&rdquo;。

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

代码

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

0
投稿

猜你喜欢

手机版 软件编程 asp之家 www.aspxhome.com