乐趣区

关于flutter:在-Flutter-和-Dart-中取消-Future-的-3-种方法

作者:坚果

公众号:” 大前端之旅 ”

华为云享专家,InfoQ 签约作者,阿里云专家博主,51CTO 博客首席体验官,开源我的项目 GVA 成员之一,专一于大前端技术的分享,包含 Flutter, 小程序, 安卓,VUE,JavaScript。

本文将疏导您理解在 Flutter 和 Dart 中勾销 future 的 3 种不同办法。

应用异步包(举荐)

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();

为了更分明,请参阅上面的理论示例。

残缺示例

利用预览

咱们要构建的应用程序有一个浮动按钮。按下此按钮时,将开始异步操作(这须要 5 秒能力实现)。按钮的背景从靛蓝变为红色,其标签从“开始”变为“勾销”,当初您能够应用它来勾销 Future。

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

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

代码

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。从其中抉择一个以在您的应用程序中实现,以使其在解决异步工作时更加强壮和吸引人。

退出移动版