Flutter | Dio网络请求实战

一、为什么选择 Dio?

Flutter 内置的 http 包可以满足简单请求,但在实际开发中,我们往往需要:

  • 统一的 BaseURL 和超时配置
  • 拦截器(请求头注入、Token 刷新、日志打印)
  • 更清晰的 错误处理
  • 支持 GET / POST / 文件上传 等多种请求方式

Dio 是 Flutter/Dart 生态中最流行的 HTTP 客户端库,功能强大、API 设计友好。本项目使用的是 Dio 5.x^5.9.0)。


二、项目依赖配置

pubspec.yaml 中添加依赖:

yaml 复制代码
dependencies:
  dio: ^5.9.0

安装依赖:

bash 复制代码
flutter pub get

三、第一步:最简单的 GET 请求

项目中的 lib/Dio的简单使用.dart 展示了最基础的用法------创建一个 Dio 实例,直接发起 GET 请求:

dart 复制代码
import 'package:dio/dio.dart';

void main(List<String> args) {
  Dio().get("https://geek.itheima.net/v1_0/channels").then((res){
    print(res);
  });
}

要点:

概念 说明
Dio() 创建一个 Dio 实例
.get(url) 发起 GET 请求,返回 Future<Response>
.then() 用回调处理响应(也可用 async/await

这种方式适合快速验证接口,但每次新建 Dio() 实例、硬编码完整 URL,不利于维护。接下来我们把它封装成工具类。


四、封装 DioUtils 工具类

lib/Dio工具封装案例.dartlib/main.dart 中都实现了 DioUtils,核心思路一致:单例 Dio 实例 + 统一配置 + 拦截器 + 对外暴露简洁 API

4.1 基础配置:BaseURL 与超时

dart 复制代码
final Dio _dio = Dio();

_dio.options
  ..baseUrl = "https://geek.itheima.net/v1_0/"
  ..connectTimeout = Duration(seconds: 10)   // 连接超时
  ..sendTimeout = Duration(seconds: 10)     // 发送超时
  ..receiveTimeout = Duration(seconds: 10); // 接收超时

这里使用了 Dart 的 级联操作符 ..,可以在同一对象上连续赋值,写法更简洁。

配置 baseUrl 后,请求时只需传入相对路径 "channels",Dio 会自动拼接为完整 URL。

4.2 拦截器:请求 / 响应 / 错误三阶段

dart 复制代码
_dio.interceptors.add(InterceptorsWrapper(
  onRequest: (options, handler) {
    // 请求发出前:可加 Token、公共 Header、日志等
    handler.next(options);
  },
  onResponse: (response, handler) {
    if (response.statusCode! >= 200 && response.statusCode! <= 300) {
      handler.next(response); // 状态码正常,继续传递
      return;
    }
    // 非 2xx 状态码,转为异常
    handler.reject(DioException(
      requestOptions: response.requestOptions,
      response: response,
      message: "状态码${response.statusCode}",
    ));
  },
  onError: (DioException e, handler) {
    handler.reject(e); // 网络错误、超时等
  },
));

拦截器的典型用途:

复制代码
请求流程:
  onRequest  →  服务器  →  onResponse / onError
     ↑                          ↓
  注入 Token              统一解析业务码
  打印日志                错误提示 / 重试

4.3 对外暴露 GET 方法

Dio工具封装案例.dart 中的版本会直接返回 response.data,并在内部捕获异常:

dart 复制代码
Future<dynamic> get(String url, {Map<String, dynamic>? queryParameters}) async {
  try {
    Response response = await _dio.get(url, queryParameters: queryParameters);
    return response.data;
  } on DioException catch (e) {
    return e.message;
  }
}

main.dart 中的版本则返回完整的 Response,由调用方自行解析:

dart 复制代码
Future<Response<dynamic>> get(String url, {Map<String, dynamic>? queryParameters}) async {
  return await _dio.get(url, queryParameters: queryParameters);
}

两种写法各有取舍:前者调用更简单,后者保留更多响应信息(状态码、Header 等)。


五、在 Flutter UI 中展示数据

main.dartDioUtils 与 Flutter 界面结合,请求频道列表并用 GridView 展示:

dart 复制代码
class _MainPageState extends State<MainPage> {
  List<Map<String, dynamic>> _list = [];

  @override
  void initState() {
    super.initState();
    _getChannels();
  }

  void _getChannels() async {
    Response<dynamic> res = await DioUtils().get("channels");
    Map<String, dynamic> result = res.data as Map<String, dynamic>;
    List data = result["data"]["channels"] as List;
    _list = data.cast<Map<String, dynamic>>();
    setState(() {}); // 触发 UI 刷新
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text("Dio工具类显示数据")),
        body: GridView.extent(
          maxCrossAxisExtent: 140,
          children: List.generate(_list.length, (index) {
            return ChannelItem(item: _list[index]);
          }),
        ),
      ),
    );
  }
}

数据流:

复制代码
initState()
    ↓
DioUtils().get("channels")
    ↓
解析 JSON → result["data"]["channels"]
    ↓
setState() → GridView 渲染 ChannelItem

接口返回的数据结构大致为:

json 复制代码
{
  "data": {
    "channels": [
      { "id": 1, "name": "推荐" },
      { "id": 2, "name": "HTML" }
    ]
  }
}

六、项目文件结构一览

复制代码
lib/
├── Dio的简单使用.dart      # 入门:一行 GET 请求
├── Dio工具封装案例.dart    # 进阶:DioUtils 封装 + 命令行测试
└── main.dart               # 实战:DioUtils + Flutter UI 展示

学习路径建议:简单使用 → 工具封装 → UI 集成,由浅入深。


七、实现效果


八、总结

阶段 文件 核心内容
入门 Dio的简单使用.dart Dio().get(url) 一行发请求
封装 Dio工具封装案例.dart BaseURL、超时、拦截器、get() 方法
实战 main.dart 异步请求 + JSON 解析 + GridView 展示

Dio 的核心价值在于 可配置、可拦截、可扩展 。本项目从 7 行的简单示例,到带拦截器的工具类,再到完整的 UI 数据流,构成了一条清晰的学习曲线。掌握这套模式后,POST 请求、文件上传、下载进度等能力都可以在同一套 DioUtils 上扩展。

相关推荐
周末也要写八哥1 小时前
C++中单线程方式之无脑上锁
java·开发语言·c++
向上的车轮1 小时前
Next.js 入门指南:从零到一构建全栈应用
开发语言·javascript·ecmascript
freeinlife'1 小时前
精准秒表计时器实现---基于js
开发语言·前端·javascript
東隅已逝,桑榆非晚1 小时前
新手入门指南:认识 C 语言文件操作(上)
c语言·开发语言·笔记
cany10001 小时前
C++ -- 动态内存分配和释放(new/delete)
开发语言·c++
王文?问2 小时前
ESP32-S3 实战教程:本地语音识别控制 Web 塔防游戏,从固件到前端完整跑通
前端·游戏·语音识别
brycegao3212 小时前
Vue3+Go 全栈项目上线阿里云|从 0 到 1 踩坑全纪录
开发语言·阿里云·golang
帅次2 小时前
讯飞与腾讯云:Android 实时语音识别服务对比选择
android·ios·微信小程序·小程序·android studio·android runtime
ch.ju2 小时前
Java Programming Chapter 4——cite
java·开发语言