詳解Flutter和Dart取消Future的三種方法
使用異步包(推薦)
async包由 Dart 編程語(yǔ)言的作者開(kāi)發(fā)和發(fā)布。它提供了dart:async風(fēng)格的實(shí)用程序來(lái)增強(qiáng)異步計(jì)算??梢詭椭覀?nèi)∠鸉uture的是CancelableOperation類:
var myCancelableFuture = CancelableOperation.fromFuture( Future<T> inner, { FutureOr onCancel()? } ) ? // call the cancel() method to cancel the future myCancelableFuture.cancel();
為了更清楚,請(qǐng)參閱下面的實(shí)際示例。
完整示例
應(yīng)用預(yù)覽
我們要構(gòu)建的應(yīng)用程序有一個(gè)浮動(dòng)按鈕。按下此按鈕時(shí),將開(kāi)始異步操作(這需要 5 秒才能完成)。按鈕的背景從靛藍(lán)變?yōu)榧t色,其標(biāo)簽從“開(kāi)始”變?yōu)?ldquo;取消”,現(xiàn)在您可以使用它來(lái)取消Future。
- 如果您在Future完成前 5 秒內(nèi)點(diǎn)擊取消按鈕,屏幕將顯示“Future已被取消”。
- 如果您什么都不做,則 5 秒后屏幕將顯示“Future completed”。
一個(gè)演示價(jià)值超過(guò)一千字:
代碼
1.通過(guò)執(zhí)行以下操作安裝異步包:
flutter pub add async
然后運(yùn)行:
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() 方法
這種方法既快速又簡(jiǎn)單。但是,它不是很靈活。
使用timeout()方法,您可以限制Future的時(shí)間(例如 3 秒)。如果 future 及時(shí)完成,它的值將被返回。另一方面,如果Future超過(guò)限制時(shí)間,將執(zhí)行onTimeout函數(shù):
Future<T> timeout( Duration timeLimit, {FutureOr<T> onTimeout()?} )
快速示例
創(chuàng)建一個(gè)虛擬的Future:
Future<String?> _myFuture() async { await Future.delayed(const Duration(seconds: 10)); return 'Future completed'; }
設(shè)置超時(shí) 3 秒:
_myFuture().timeout( const Duration(seconds: 3), onTimeout: () => 'The process took too much time to finish. Please try again later', );
將Future轉(zhuǎn)換為流
您可以使用 Future 類的asStream()方法來(lái)創(chuàng)建一個(gè)包含原始Future結(jié)果的流?,F(xiàn)在您可以取消對(duì)該流的訂閱。
快速示例
// 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();
請(qǐng)注意,這個(gè)快速示例僅簡(jiǎn)要描述了事物的工作原理。您必須對(duì)其進(jìn)行修改以使其可在現(xiàn)有項(xiàng)目中運(yùn)行。
結(jié)論
你已經(jīng)學(xué)會(huì)了不止一種方法來(lái)取消 Flutter 中的Future。從其中選擇一個(gè)以在您的應(yīng)用程序中實(shí)現(xiàn),以使其在處理異步任務(wù)時(shí)更加健壯和吸引人。
以上就是詳解Flutter和Dart取消Future的三種方法的詳細(xì)內(nèi)容,更多關(guān)于Flutter Dart取消Future的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Android之RecyclerView輕松實(shí)現(xiàn)下拉刷新和加載更多示例
本篇文章主要介紹了Android之RecyclerView輕松實(shí)現(xiàn)下拉刷新和加載更多示例,非常具有實(shí)用價(jià)值,需要的朋友可以參考下。2017-02-02Android入門之TableLayout應(yīng)用解析(一)
這篇文章主要介紹了Android入門之TableLayout應(yīng)用,需要的朋友可以參考下2014-08-08Android中Handler與Message的簡(jiǎn)單實(shí)例
這篇文章主要介紹了Android中Handler與Message的簡(jiǎn)單實(shí)例的相關(guān)資料,這里提供實(shí)例來(lái)說(shuō)明線程Handler與message 的結(jié)合使用,需要的朋友可以參考下2017-08-08Android開(kāi)發(fā)使用URLConnection進(jìn)行網(wǎng)絡(luò)編程詳解
這篇文章主要介紹了Android開(kāi)發(fā)使用URLConnection進(jìn)行網(wǎng)絡(luò)編程,結(jié)合實(shí)例形式分析了Android URLConnection對(duì)象創(chuàng)建、屬性、方法及相關(guān)使用技巧,需要的朋友可以參考下2018-01-01Android編程實(shí)現(xiàn)使用Intent傳輸包含自定義類的ArrayList示例
這篇文章主要介紹了Android編程實(shí)現(xiàn)使用Intent傳輸包含自定義類的ArrayList,涉及Android對(duì)象序列化、反序列化、Intent數(shù)據(jù)傳輸?shù)认嚓P(guān)操作技巧,需要的朋友可以參考下2017-08-08