Flutter任务取消管理插件cancelation_token的使用

发布于 1周前 作者 vueper 来自 Flutter

Flutter任务取消管理插件cancelation_token的使用

cancelation_token

cancelation_token包提供了取消令牌的接口以及各种实现,可以帮助开发者更好地管理和取消异步任务。以下是该包提供的几种主要类型的取消令牌:

  • CancelableToken:可以通过编程方式取消的任务。
  • CompositeToken:当任何一个或所有令牌被取消时,它也会被取消。
  • TimeoutToken:在超时后自动取消。

示例

超时取消长时间运行的任务

下面是一个示例,展示了如何在超时后取消一个长时间运行的任务。

示例代码

import 'package:cancelation_token/cancelation_token.dart';

void main() async {
  final timeout = Duration(seconds: 5);
  final errorOnTimeout = CanceledException.withStackTrace('Too long!');
  final token = TimeoutToken(timeout, errorOnTimeout);
  token.ensureStarted();

  try {
    await longProcess(token);
  } on CanceledException catch (ex, st) {
    print(ex.message);
    print(ex.stackTrace);
    print(st);
  }
}

Future<void> longProcess(CancelationToken token) async {
  // 模拟一个非常长的任务
  while (true) {
    token.throwIfCanceled();
    await Future.delayed(const Duration(milliseconds: 100));
  }
}

完整示例项目结构

为了更全面地展示cancelation_token的使用,以下是一个完整的示例项目结构,包括三种不同类型的取消令牌的使用示例。

main.dart

import 'cancelable_example.dart' as cancelable;
import 'composite_example.dart' as composite;
import 'timeout_example.dart' as timeout;

void main() async {
  print('CANCELABLE EXAMPLE');
  await cancelable.main();

  print('');
  print('TIMEOUT EXAMPLE');
  await timeout.main();

  print('');
  print('COMPOSITE EXAMPLE');
  await composite.main();
}

cancelable_example.dart

import 'package:cancelation_token/cancelation_token.dart';

Future<void> main() async {
  final token = CancelableToken();
  
  // 启动一个长时间任务
  Future<void> longTask() async {
    for (int i = 0; i < 10; i++) {
      token.throwIfCanceled();
      print('Step $i');
      await Future.delayed(Duration(seconds: 1));
    }
  }

  // 启动任务
  final task = longTask();

  // 模拟用户取消操作
  await Future.delayed(Duration(seconds: 3));
  token.cancel();

  try {
    await task;
  } on CanceledException catch (ex) {
    print('Task was canceled: ${ex.message}');
  }
}

composite_example.dart

import 'package:cancelation_token/cancelation_token.dart';

Future<void> main() async {
  final token1 = CancelableToken();
  final token2 = CancelableToken();
  final compositeToken = CompositeToken([token1, token2]);

  // 启动一个长时间任务
  Future<void> longTask() async {
    for (int i = 0; i < 10; i++) {
      compositeToken.throwIfCanceled();
      print('Step $i');
      await Future.delayed(Duration(seconds: 1));
    }
  }

  // 启动任务
  final task = longTask();

  // 模拟用户取消操作
  await Future.delayed(Duration(seconds: 3));
  token1.cancel(); // 取消其中一个令牌会取消整个复合令牌

  try {
    await task;
  } on CanceledException catch (ex) {
    print('Task was canceled: ${ex.message}');
  }
}

timeout_example.dart

import 'package:cancelation_token/cancelation_token.dart';

Future<void> main() async {
  final timeout = Duration(seconds: 5);
  final errorOnTimeout = CanceledException.withStackTrace('Too long!');
  final token = TimeoutToken(timeout, errorOnTimeout);
  token.ensureStarted();

  // 启动一个长时间任务
  Future<void> longTask() async {
    for (int i = 0; i < 10; i++) {
      token.throwIfCanceled();
      print('Step $i');
      await Future.delayed(Duration(seconds: 1));
    }
  }

  try {
    await longTask();
  } on CanceledException catch (ex) {
    print('Task was canceled: ${ex.message}');
  }
}

通过这些示例,您可以了解如何在Flutter应用中使用cancelation_token来管理异步任务的取消。希望这些示例对您有所帮助!


更多关于Flutter任务取消管理插件cancelation_token的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter任务取消管理插件cancelation_token的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


在Flutter中,cancelation_token 插件可以帮助你管理任务的取消。这在处理长时间运行的操作(如网络请求、文件I/O等)时非常有用。下面是一个关于如何使用 cancelation_token 插件的详细代码示例。

首先,确保你已经在 pubspec.yaml 文件中添加了 cancelation_token 依赖:

dependencies:
  flutter:
    sdk: flutter
  cancelation_token: ^x.y.z  # 请替换为最新版本号

然后运行 flutter pub get 来获取依赖。

接下来,我们可以编写一个示例代码来展示如何使用 cancelation_token。在这个示例中,我们将模拟一个长时间运行的任务,并展示如何取消它。

import 'package:flutter/material.dart';
import 'package:cancelation_token/cancelation_token.dart';
import 'dart:async';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Cancelation Token Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final CancelationToken _cancelationToken = CancelationToken();
  bool _isRunning = false;
  String _status = 'Not started';

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter Cancelation Token Demo'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(_status),
            SizedBox(height: 20),
            ElevatedButton(
              onPressed: _isRunning ? null : () => _startLongRunningTask(),
              child: Text('Start Task'),
            ),
            SizedBox(height: 10),
            ElevatedButton(
              onPressed: _isRunning ? () => _cancelTask() : null,
              child: Text('Cancel Task'),
            ),
          ],
        ),
      ),
    );
  }

  Future<void> _startLongRunningTask() async {
    setState(() {
      _isRunning = true;
      _status = 'Running...';
    });

    try {
      await _performLongRunningTask(_cancelationToken);
      setState(() {
        _status = 'Task completed successfully';
      });
    } catch (e) {
      if (e is CancelationTokenException) {
        setState(() {
          _status = 'Task was cancelled';
        });
      } else {
        setState(() {
          _status = 'Task failed: ${e.toString()}';
        });
      }
    } finally {
      setState(() {
        _isRunning = false;
      });
    }
  }

  Future<void> _performLongRunningTask(CancelationToken cancelationToken) async {
    for (int i = 0; i < 10; i++) {
      if (cancelationToken.isCancelled) {
        throw CancelationTokenException('Task was cancelled by user');
      }
      
      await Future.delayed(Duration(seconds: 1));
      print('Task progress: $i'); // 模拟任务进度
    }
    // 模拟任务完成
  }

  void _cancelTask() {
    _cancelationToken.cancel();
  }
}

class CancelationTokenException implements Exception {
  final String message;

  CancelationTokenException(this.message);

  @override
  String toString() => message;
}

代码说明:

  1. 依赖添加:在 pubspec.yaml 中添加 cancelation_token 依赖。
  2. UI部分
    • 使用 ElevatedButton 创建了两个按钮,一个用于启动任务,另一个用于取消任务。
    • 使用 Text 组件显示任务状态。
  3. 状态管理
    • 使用 _isRunning 变量来跟踪任务是否正在运行。
    • 使用 _status 变量来显示任务的状态信息。
  4. 任务管理
    • _startLongRunningTask 方法启动长时间运行的任务,并在任务完成后更新状态。
    • _performLongRunningTask 方法模拟一个长时间运行的任务,每秒钟打印一次进度,并检查 CancelationToken 是否被取消。
    • _cancelTask 方法取消任务。
  5. 自定义异常
    • 定义了 CancelationTokenException 类来处理取消任务时的异常。

通过这种方式,你可以轻松地在Flutter应用中管理任务的取消。

回到顶部