Flutter网络请求取消管理插件cancellation_token_http的使用

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

Flutter网络请求取消管理插件cancellation_token_http的使用

Dart Cancellation Token: HTTP

cancellation_token_http 是Dart的HTTP包的一个分支,它通过 cancellation_token 插件实现了请求取消功能。它基于HTTP包1.2.2版本。

功能特性

  • 保留了原始HTTP包的所有功能。
  • 使用 CancellationTokens 取消HTTP请求。
  • 可以与 cancellation_token 包一起使用,用单个token来发起可取消的API请求并解析响应JSON,甚至可以在隔离区中进行取消操作。

使用方法

此包保持了与基础HTTP包相同的API,只是添加了可选的 cancellationToken 参数。更多关于 CancellationTokens 的信息可以参考 CancellationTokens

下面是一个简单的例子,展示了如何使用 cancellation_token_http 发起一个GET请求,并在必要时取消它:

import 'package:cancellation_token_http/http.dart' as http;

void main() async {
  var token = http.CancellationToken();
  
  try {
    // 发起GET请求
    var response = await http.get(
      Uri.parse('https://jsonplaceholder.typicode.com/posts/1'),
      cancellationToken: token,
    );
    
    if (response.statusCode == 200) {
      print('Response body: ${response.body}');
    } else {
      print('Request failed with status: ${response.statusCode}');
    }
  } on http.CancelledException {
    print('Request was cancelled');
  }

  // 模拟用户取消请求
  // token.cancel(); 
}

解析JSON并在隔离区中取消

当需要在隔离区中解析JSON并且该操作也是可取消的时候,你可以这样做:

import 'package:cancellation_token/cancellation_token.dart';
import 'package:cancellation_token_http/http.dart' as http;
import 'dart:convert';

class Post {
  final int userId;
  final int id;
  final String title;
  final String body;

  Post({required this.userId, required this.id, required this.title, required this.body});

  factory Post.fromJson(Map<String, dynamic> json) {
    return Post(
      userId: json['userId'],
      id: json['id'],
      title: json['title'],
      body: json['body']
    );
  }
}

Future<void> fetchPost() async {
  var token = CancellationToken();
  try {
    var response = await http.get(
      Uri.parse('https://jsonplaceholder.typicode.com/posts/1'),
      cancellationToken: token,
    );

    // 假设我们有一个函数 parseJson 在另一个 isolate 中执行解析任务
    var post = cancellableCompute(parseJson, response.body, token);
    print('Post parsed successfully: $post');
  } on CancelledException {
    print('Request and parse cancelled');
  }
}

Post parseJson(String jsonString) {
  final Map<String, dynamic> decodedJson = json.decode(jsonString);
  return Post.fromJson(decodedJson);
}

示例代码

这里提供了一个完整的示例,演示了不带取消、手动取消以及超时取消三种情况下的请求处理方式:

import 'dart:convert' as convert;
import 'package:cancellation_token/cancellation_token.dart';
import 'package:cancellation_token_http/http.dart' as http;

void main(List<String> arguments) async {
  var url = Uri.https('www.googleapis.com', '/books/v1/volumes', {'q': '{http}'});
  
  await standardRequest(url);
  await manualCancelRequest(url);
  await timeoutCancelRequest(url);
}

/// 不带取消的普通请求
Future<void> standardRequest(Uri url) async {
  print('Performing request without cancellation...');
  
  var response = await http.get(url);
  if (response.statusCode == 200) {
    var jsonResponse = convert.jsonDecode(response.body) as Map<String, dynamic>;
    var itemCount = jsonResponse['totalItems'];
    print('Number of books about http: $itemCount.');
  } else {
    print('Request failed with status: ${response.statusCode}.');
  }
}

/// 手动取消请求
Future<void> manualCancelRequest(Uri url) async {
  print('Performing request with a manual cancellation...');
  
  var cancellationToken = http.CancellationToken()..cancel();

  try {
    var response = await http.get(url, cancellationToken: cancellationToken);
    if (response.statusCode == 200) {
      var jsonResponse = convert.jsonDecode(response.body) as Map<String, dynamic>;
      var itemCount = jsonResponse['totalItems'];
      print('Number of books about http: $itemCount.');
    } else {
      print('Request failed with status: ${response.statusCode}.');
    }
  } on http.CancelledException {
    print('Request cancelled manually');
  }
}

/// 超时取消请求
Future<void> timeoutCancelRequest(Uri url) async {
  print('Performing request with a 5 second timeout cancellation...');
  
  var cancellationToken = http.TimeoutCancellationToken(Duration(seconds: 5));

  try {
    var response = await http.get(url, cancellationToken: cancellationToken);
    if (response.statusCode == 200) {
      var jsonResponse = convert.jsonDecode(response.body) as Map<String, dynamic>;
      var itemCount = jsonResponse['totalItems'];
      print('Number of books about http: $itemCount.');
    } else {
      print('Request failed with status: ${response.statusCode}.');
    }
  } on TimeoutException {
    print('Request cancelled by timeout');
  }
}

以上就是关于 cancellation_token_http 插件的基本介绍和使用方法。希望这些信息能帮助您更好地理解和使用这个强大的工具来管理和优化您的Flutter应用中的网络请求。


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

1 回复

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


当然,以下是如何在Flutter项目中使用cancellation_token_http插件进行网络请求取消管理的示例代码。

1. 添加依赖

首先,在你的pubspec.yaml文件中添加cancellation_token_http依赖:

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

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

2. 导入插件

在你的Dart文件中导入插件:

import 'package:cancellation_token_http/cancellation_token_http.dart';
import 'package:dio/dio.dart';

3. 配置和使用

以下是一个完整的示例,展示了如何使用cancellation_token_http进行网络请求并管理取消操作:

import 'package:flutter/material.dart';
import 'package:cancellation_token_http/cancellation_token_http.dart';
import 'package:dio/dio.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: NetworkRequestScreen(),
    );
  }
}

class NetworkRequestScreen extends StatefulWidget {
  @override
  _NetworkRequestScreenState createState() => _NetworkRequestScreenState();
}

class _NetworkRequestScreenState extends State<NetworkRequestScreen> {
  final CancellationTokenSource _cancellationTokenSource = CancellationTokenSource();
  var _responseData;
  var _error;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Network Request with Cancellation'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            TextButton(
              onPressed: () => _fetchData(),
              child: Text('Fetch Data'),
            ),
            SizedBox(height: 20),
            if (_error != null)
              Text(
                'Error: $_error',
                style: TextStyle(color: Colors.red),
              ),
            if (_responseData != null)
              Text(
                'Response: $_responseData',
                style: TextStyle(color: Colors.green),
              ),
            ElevatedButton(
              onPressed: () => _cancelRequest(),
              child: Text('Cancel Request'),
            ),
          ],
        ),
      ),
    );
  }

  void _fetchData() async {
    setState(() {
      _responseData = null;
      _error = null;
    });

    try {
      Response<String> response = await Dio()
          .get(
            'https://jsonplaceholder.typicode.com/posts/1',
            options: Options(
              headers: {
                'Content-Type': 'application/json',
              },
            ),
            cancelToken: _cancellationTokenSource.token,
          )
          .catchErr((err) {
            if (err is CancelTokenError) {
              print('Request canceled');
            } else {
              print('Request failed: ${err.message}');
            }
            throw err;
          });

      setState(() {
        _responseData = response.data;
      });
    } catch (e) {
      setState(() {
        _error = e.toString();
      });
    }
  }

  void _cancelRequest() {
    _cancellationTokenSource.cancel('Request was canceled by the user.');
  }
}

解释

  1. 依赖添加:在pubspec.yaml文件中添加cancellation_token_http依赖。
  2. 导入插件:在Dart文件中导入cancellation_token_httpdio
  3. 创建CancellationTokenSource:用于管理取消令牌。
  4. 发送网络请求:使用Dio().get方法发送请求,并将cancelToken参数设置为_cancellationTokenSource.token
  5. 取消请求:调用_cancellationTokenSource.cancel方法取消请求。

这个示例展示了如何在Flutter应用中通过cancellation_token_http插件管理网络请求的取消操作。希望这对你有所帮助!

回到顶部