首先要明確的一點(diǎn)是, 在dart協(xié)程式的編程語(yǔ)言中, 是無法中斷一個(gè)Future的執(zhí)行的, 我們所能做的只能是取消一個(gè)async代碼塊的回調(diào), 也就是說一段異步代碼塊執(zhí)行后, 準(zhǔn)備繼續(xù)執(zhí)行后續(xù)的回調(diào)代碼時(shí), 由于已經(jīng)被取消, 而中止了整個(gè)過程.
由于在dart中有回調(diào)機(jī)制并能被中止的有Futhre.then()和Stream.listen(), 所以下面就有相應(yīng)的實(shí)現(xiàn)方法吃媒。
方法1: 使用CancelableOperation
下面是一個(gè)異步獲取數(shù)據(jù), 當(dāng)頁(yè)面銷毀時(shí)中斷渲染的示例代碼:
import 'package:async/async.dart';
void loadPageDatas() async {
CancelableOperation cancelTask = CancelableOperation.fromFuture(
Future(() async {
print('start query datas');
await Future.delayed(Duration(seconds: 6));
print('end query datas');
return "value";
}),
onCancel: () => print('disposed, cancel rendering.'),
);
cancelTask.value.then((val) {
print('to render tree: $val '); // 不能放在cancelTask的構(gòu)造函數(shù)中, 需要通過 cancelTask.value.then進(jìn)行添加.
});
Future.delayed(Duration(seconds: 3)).then((_) {
// when disposed
cancelTask.cancel();
});
}
有一些細(xì)節(jié), 通過源碼cancelable_operation.dart::CancelableCompleter()實(shí)現(xiàn)可以知道, 由于CancelableOperation是對(duì)Future的then進(jìn)行了接管, 判斷isCanceled標(biāo)記以決定是否需要執(zhí)行用戶提供的then(), 但這個(gè)接管是在CancelableCompleter()構(gòu)造完成后的 cancelTask.value中進(jìn)行的,
所以在CancelableOperation.fromFuture()只提供不可中斷的功能(如querying datas), 將可中斷的功能(如rendering)放在構(gòu)造完成后的.value.then中添加钓辆,
這是需要注意的,否則會(huì)出現(xiàn)即使cancel()后仍會(huì)執(zhí)行的情況呀非。
CancelableOperation 類的本質(zhì)是有個(gè) CancelableCompleter 類, 在其中完成了cancel的操作, 可以閱讀源碼.
方法2:使用Stream.
同樣的示例代碼, 很簡(jiǎn)單:
Future<String> getData() async {
print('into getData');
await Future.delayed(Duration(seconds: 5));
print('leave getData');
return "value";
}
void loadPageDatas() async {
StreamSubscription<String> dataSub =
getData().asStream().listen((String data) {
print('rendering data: $data');
});
Future.delayed(Duration(seconds: 3), () => dataSub.cancel());
}
代碼比較清晰, 不多解釋了燎孟。
參考來源:
https://dart.academy/how_cancel_future/
有個(gè)題外話禽作,在使用Future.delayed(Duration(seconds: 3, milliseconds: 100))時(shí),要小心精度問題揩页,比如Duration(seconds: 3, milliseconds: 100)有可能比Duration(seconds: 3) 要先被執(zhí)行旷偿,這牽涉到task的調(diào)度,還沒有深究爆侣,有時(shí)間了再做研究萍程。