詳解Flutter和Dart取消Future的三種方法
使用異步包(推薦)
async包由 Dart 編程語(yǔ)言的作者開發(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í),將開始異步操作(這需要 5 秒才能完成)。按鈕的背景從靛藍(lán)變?yōu)榧t色,其標(biāo)簽從“開始”變?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é)果的流。現(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)文章
OpenGL Shader實(shí)例分析(2)繪制心臟跳動(dòng)效果
這篇文章主要為大家詳細(xì)介紹了OpenGL Shader實(shí)例分析第2篇,繪制心臟跳動(dòng)效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-02-02
android 控件同時(shí)監(jiān)聽單擊和雙擊實(shí)例
這篇文章主要介紹了android 控件同時(shí)監(jiān)聽單擊和雙擊實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-08-08
Android自定義View實(shí)現(xiàn)加載進(jìn)度條效果
這篇文章主要為大家詳細(xì)介紹了Android自定義View實(shí)現(xiàn)加載進(jìn)度條效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-05-05
Android 防止多次重復(fù)點(diǎn)擊的三種方法的示例
本篇文章主要介紹了Android 防止多次重復(fù)點(diǎn)擊的三種方法的示例,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-03-03
android自定義波浪加載動(dòng)畫的實(shí)現(xiàn)代碼
這篇文章主要為大家詳細(xì)介紹了android自定義波浪加載動(dòng)畫,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-11-11
Android開發(fā)-之環(huán)境的搭建(圖文詳解)
這篇文章主要介紹了Android開發(fā)-之環(huán)境的搭建(圖文詳解),具有一定的參考價(jià)值,有興趣的可以了解一下。2016-11-11
Android使用ShareSDK實(shí)現(xiàn)應(yīng)用分享的功能
這篇文章主要為大家詳細(xì)介紹了Android使用ShareSDK實(shí)現(xiàn)應(yīng)用分享的功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-05-05
安卓(Android)實(shí)現(xiàn)3DTouch效果
3DTouch是什么效果的大家應(yīng)該都知道了。本文將介紹在Android中如何實(shí)現(xiàn)3DTouch的效果,有需要的可以參考學(xué)習(xí)。2016-08-08

