Flutter网络请求插件dio的使用

Flutter网络请求插件dio的使用

简介

dio 是一个强大且灵活的HTTP客户端库,适用于Dart和Flutter。它支持全局配置、拦截器、FormData、请求取消、文件上传/下载、超时设置、自定义适配器、转换器等特性。

Pub Dev

快速开始

安装

pubspec.yaml 文件中添加 dio 依赖:

dependencies:
  dio: ^5.0.0

简单使用示例

import 'package:dio/dio.dart';

void main() async {
  final dio = Dio();
  try {
    final response = await dio.get('https://jsonplaceholder.typicode.com/posts/1');
    print(response.data);
  } catch (e) {
    print(e);
  }
}

请求选项与配置

创建实例并设置默认配置

推荐在一个项目中使用 Dio 的单例模式来管理配置。

final dio = Dio(BaseOptions(
  baseUrl: 'https://api.example.com',
  connectTimeout: Duration(seconds: 5),
  receiveTimeout: Duration(seconds: 3),
));

发送GET请求

void getHttp() async {
  try {
    final response = await dio.get('/posts', queryParameters: {'userId': 1});
    print(response.data);
  } catch (e) {
    print(e);
  }
}

发送POST请求

void postHttp() async {
  try {
    final response = await dio.post('/posts', data: {'title': 'foo', 'body': 'bar', 'userId': 1});
    print(response.data);
  } catch (e) {
    print(e);
  }
}

并发请求

void concurrentRequests() async {
  try {
    final responses = await Future.wait([
      dio.get('/posts/1'),
      dio.get('/comments/1')
    ]);
    print(responses);
  } catch (e) {
    print(e);
  }
}

文件下载

void downloadFile() async {
  try {
    final dir = await getTemporaryDirectory();
    await dio.download('https://example.com/file.zip', '${dir.path}/file.zip');
  } catch (e) {
    print(e);
  }
}

拦截器

可以为每个 Dio 实例添加一个或多个拦截器,用于拦截请求、响应和错误。

自定义拦截器

class LoggingInterceptor extends Interceptor {
  @override
  void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
    print('Request[${options.method}] => PATH: ${options.path}');
    super.onRequest(options, handler);
  }

  @override
  void onResponse(Response response, ResponseInterceptorHandler handler) {
    print('Response[${response.statusCode}] => PATH: ${response.requestOptions.path}');
    super.onResponse(response, handler);
  }

  @override
  void onError(DioException err, ErrorInterceptorHandler handler) {
    print('Error[${err.response?.statusCode}] => PATH: ${err.requestOptions.path}');
    super.onError(err, handler);
  }
}

// 使用拦截器
dio.interceptors.add(LoggingInterceptor());

错误处理

当发生错误时,Dio 会将 Error/Exception 包装成 DioException

try {
  await dio.get('https://api.example.com/not-exist');
} on DioException catch (e) {
  if (e.response != null) {
    print(e.response.data);
  } else {
    print(e.message);
  }
}

表单数据提交

void sendFormData() async {
  final formData = FormData.fromMap({
    'name': 'flutter',
    'date': DateTime.now().toIso8601String(),
    'file': await MultipartFile.fromFile('./example/upload.txt', filename: 'upload.txt'),
  });
  try {
    final response = await dio.post('/upload', data: formData);
    print(response.data);
  } catch (e) {
    print(e);
  }
}

取消请求

可以通过 CancelToken 来取消请求。

void cancelRequest() async {
  final cancelToken = CancelToken();
  try {
    await dio.get('https://api.example.com/data', cancelToken: cancelToken);
  } catch (e) {
    if (CancelToken.isCancel(e)) {
      print('Request canceled: ${e.message}');
    } else {
      print(e);
    }
  }
  // 取消请求
  cancelToken.cancel('Operation canceled by the user.');
}

示例代码

以下是一个完整的示例,演示了如何使用 dio 进行简单的 GET 和 POST 请求:

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

void main() async {
  final dio = Dio();

  // 添加日志拦截器
  dio.interceptors.add(LoggingInterceptor());

  // 发送GET请求
  await getHttp(dio);

  // 发送POST请求
  await postHttp(dio);

  // 并发请求
  await concurrentRequests(dio);

  // 下载文件
  await downloadFile(dio);
}

Future<void> getHttp(Dio dio) async {
  try {
    final response = await dio.get('https://jsonplaceholder.typicode.com/posts/1');
    print('GET Response: ${response.data}');
  } catch (e) {
    print('GET Error: $e');
  }
}

Future<void> postHttp(Dio dio) async {
  try {
    final response = await dio.post('https://jsonplaceholder.typicode.com/posts', data: {'title': 'foo', 'body': 'bar', 'userId': 1});
    print('POST Response: ${response.data}');
  } catch (e) {
    print('POST Error: $e');
  }
}

Future<void> concurrentRequests(Dio dio) async {
  try {
    final responses = await Future.wait([
      dio.get('https://jsonplaceholder.typicode.com/posts/1'),
      dio.get('https://jsonplaceholder.typicode.com/comments/1')
    ]);
    print('Concurrent Responses: $responses');
  } catch (e) {
    print('Concurrent Error: $e');
  }
}

Future<void> downloadFile(Dio dio) async {
  try {
    final dir = await getTemporaryDirectory();
    await dio.download('https://jsonplaceholder.typicode.com/posts/1', '${dir.path}/post.json');
    print('File downloaded successfully');
  } catch (e) {
    print('Download Error: $e');
  }
}

通过上述内容,您可以快速上手并掌握 dio 插件的基本用法。更多高级功能请参考 官方文档


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

1 回复

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


当然,下面是一个关于如何在Flutter中使用dio插件进行网络请求的详细代码示例。dio是一个功能强大且易于使用的HTTP客户端,非常适合Flutter应用。

1. 添加依赖

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

dependencies:
  flutter:
    sdk: flutter
  dio: ^4.0.4  # 请确保使用最新版本

2. 导入dio

在你的Dart文件中导入dio库:

import 'package:dio/dio.dart';

3. 初始化Dio实例

通常,你会在应用的入口文件(如main.dart)中初始化一个全局的Dio实例,以便在整个应用中复用。

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

void main() {
  // 初始化Dio实例
  var dio = Dio();

  // 你可以在这里设置一些全局配置,比如baseURL
  dio.options.baseUrl = "https://api.example.com";

  runApp(MyApp(dio: dio));
}

class MyApp extends StatelessWidget {
  final Dio dio;

  MyApp({required this.dio});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MyHomePage(dio: dio),
    );
  }
}

4. 使用Dio进行GET请求

class MyHomePage extends StatefulWidget {
  final Dio dio;

  MyHomePage({required this.dio});

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  String? responseData;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Dio GET 请求示例'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            ElevatedButton(
              onPressed: _fetchData,
              child: Text('获取数据'),
            ),
            Text(responseData ?? '无数据'),
          ],
        ),
      ),
    );
  }

  void _fetchData() async {
    try {
      // 发起GET请求
      Response response = await widget.dio.get("/path/to/endpoint");
      // 处理响应数据
      setState(() {
        responseData = response.data.toString();
      });
    } catch (e) {
      // 处理错误
      print(e);
    }
  }
}

5. 使用Dio进行POST请求

void _postData() async {
  try {
    // 准备POST请求的数据
    var data = FormData.fromMap({
      "key1": "value1",
      "key2": "value2",
    });

    // 发起POST请求
    Response response = await widget.dio.post("/path/to/endpoint", data: data);
    // 处理响应数据
    setState(() {
      responseData = response.data.toString();
    });
  } catch (e) {
    // 处理错误
    print(e);
  }
}

你可以将_postData方法添加到_MyHomePageState类中,并在UI中添加一个按钮来触发这个POST请求:

ElevatedButton(
  onPressed: _postData,
  child: Text('发送数据'),
),

6. 完整示例

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

void main() {
  var dio = Dio();
  dio.options.baseUrl = "https://api.example.com";
  runApp(MyApp(dio: dio));
}

class MyApp extends StatelessWidget {
  final Dio dio;

  MyApp({required this.dio});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MyHomePage(dio: dio),
    );
  }
}

class MyHomePage extends StatefulWidget {
  final Dio dio;

  MyHomePage({required this.dio});

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  String? responseData;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Dio 网络请求示例'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            ElevatedButton(
              onPressed: _fetchData,
              child: Text('获取数据 (GET)'),
            ),
            ElevatedButton(
              onPressed: _postData,
              child: Text('发送数据 (POST)'),
            ),
            Text(responseData ?? '无数据'),
          ],
        ),
      ),
    );
  }

  void _fetchData() async {
    try {
      Response response = await widget.dio.get("/path/to/endpoint");
      setState(() {
        responseData = response.data.toString();
      });
    } catch (e) {
      print(e);
    }
  }

  void _postData() async {
    try {
      var data = FormData.fromMap({
        "key1": "value1",
        "key2": "value2",
      });
      Response response = await widget.dio.post("/path/to/endpoint", data: data);
      setState(() {
        responseData = response.data.toString();
      });
    } catch (e) {
      print(e);
    }
  }
}

这个示例展示了如何在Flutter中使用dio插件进行基本的GET和POST请求,并处理响应和错误。你可以根据自己的需求进一步扩展和修改这些代码。

回到顶部