当前位置: 首页 > news >正文

Flutter 网络请求与数据处理:从基础到单例封装

Flutter 网络请求与数据处理:从基础到单例封装

在 Flutter 开发中,网络请求是一个非常常见的需求,比如获取 API 数据、上传文件、处理分页加载等。为了高效地处理网络请求和数据管理,我们需要选择合适的工具并进行合理的封装。

本篇博客将详细介绍 Flutter 中网络请求的基础知识、常用库(如 httpdio),并最终实现一个单例模式的网络请求封装,帮助你在项目中高效管理网络请求。


1. 网络请求的基础知识

1.1 HTTP 请求的基本类型

  1. GET:从服务器获取数据。
  2. POST:向服务器发送数据。
  3. PUT:更新服务器上的数据。
  4. DELETE:删除服务器上的数据。

1.2 常用的网络请求库

  1. http
    • Flutter 官方提供的轻量级 HTTP 客户端。
    • 适合简单的网络请求。
  2. dio
    • 功能强大的第三方库,支持拦截器、文件上传下载、请求取消等。
    • 适合复杂的网络请求场景。

2. 使用 http 进行网络请求

2.1 安装 http

pubspec.yaml 中添加依赖:

dependencies:
  http: ^0.15.0

运行以下命令安装依赖:

flutter pub get

2.2 基本用法

GET 请求
import 'dart:convert';
import 'package:http/http.dart' as http;

void fetchData() async {
  final url = Uri.parse("https://jsonplaceholder.typicode.com/posts");
  final response = await http.get(url);

  if (response.statusCode == 200) {
    final data = json.decode(response.body);
    print("数据加载成功:$data");
  } else {
    print("请求失败,状态码:${response.statusCode}");
  }
}

void main() {
  fetchData();
}
POST 请求
void postData() async {
  final url = Uri.parse("https://jsonplaceholder.typicode.com/posts");
  final response = await http.post(
    url,
    headers: {"Content-Type": "application/json"},
    body: json.encode({"title": "Flutter", "body": "Hello World", "userId": 1}),
  );

  if (response.statusCode == 201) {
    final data = json.decode(response.body);
    print("数据提交成功:$data");
  } else {
    print("请求失败,状态码:${response.statusCode}");
  }
}

void main() {
  postData();
}

3. 使用 dio 进行网络请求

3.1 安装 dio

pubspec.yaml 中添加依赖:

dependencies:
  dio: ^5.0.0

运行以下命令安装依赖:

flutter pub get

3.2 基本用法

GET 请求
import 'package:dio/dio.dart';

void fetchData() async {
  final dio = Dio();
  final response = await dio.get("https://jsonplaceholder.typicode.com/posts");

  if (response.statusCode == 200) {
    print("数据加载成功:${response.data}");
  } else {
    print("请求失败,状态码:${response.statusCode}");
  }
}

void main() {
  fetchData();
}
POST 请求
void postData() async {
  final dio = Dio();
  final response = await dio.post(
    "https://jsonplaceholder.typicode.com/posts",
    data: {"title": "Flutter", "body": "Hello World", "userId": 1},
  );

  if (response.statusCode == 201) {
    print("数据提交成功:${response.data}");
  } else {
    print("请求失败,状态码:${response.statusCode}");
  }
}

void main() {
  postData();
}

3.3 使用拦截器

dio 提供了强大的拦截器功能,可以在请求前后进行统一处理。

示例:添加拦截器
void fetchDataWithInterceptor() async {
  final dio = Dio();

  // 添加拦截器
  dio.interceptors.add(InterceptorsWrapper(
    onRequest: (options, handler) {
      print("请求开始:${options.uri}");
      return handler.next(options);
    },
    onResponse: (response, handler) {
      print("请求成功:${response.data}");
      return handler.next(response);
    },
    onError: (error, handler) {
      print("请求失败:${error.message}");
      return handler.next(error);
    },
  ));

  final response = await dio.get("https://jsonplaceholder.typicode.com/posts");
  print(response.data);
}

void main() {
  fetchDataWithInterceptor();
}

4. 单例模式封装网络请求

在实际项目中,网络请求通常需要统一管理,比如设置基础 URL、添加拦截器、处理错误等。通过单例模式封装网络请求,可以提高代码的复用性和可维护性。

4.1 单例封装 dio

封装代码
import 'package:dio/dio.dart';

class DioClient {
  // 单例模式
  static final DioClient _instance = DioClient._internal();
  factory DioClient() => _instance;

  late Dio _dio;

  DioClient._internal() {
    _dio = Dio(BaseOptions(
      baseUrl: "https://jsonplaceholder.typicode.com",
      connectTimeout: const Duration(seconds: 10),
      receiveTimeout: const Duration(seconds: 10),
      headers: {"Content-Type": "application/json"},
    ));

    // 添加拦截器
    _dio.interceptors.add(InterceptorsWrapper(
      onRequest: (options, handler) {
        print("请求开始:${options.uri}");
        return handler.next(options);
      },
      onResponse: (response, handler) {
        print("请求成功:${response.data}");
        return handler.next(response);
      },
      onError: (error, handler) {
        print("请求失败:${error.message}");
        return handler.next(error);
      },
    ));
  }

  // GET 请求
  Future<Response> get(String path, {Map<String, dynamic>? queryParameters}) async {
    return await _dio.get(path, queryParameters: queryParameters);
  }

  // POST 请求
  Future<Response> post(String path, {Map<String, dynamic>? data}) async {
    return await _dio.post(path, data: data);
  }

  // PUT 请求
  Future<Response> put(String path, {Map<String, dynamic>? data}) async {
    return await _dio.put(path, data: data);
  }

  // DELETE 请求
  Future<Response> delete(String path, {Map<String, dynamic>? data}) async {
    return await _dio.delete(path, data: data);
  }
}

4.2 使用封装的 DioClient

GET 请求
void fetchData() async {
  final dioClient = DioClient();
  final response = await dioClient.get("/posts");

  if (response.statusCode == 200) {
    print("数据加载成功:${response.data}");
  } else {
    print("请求失败,状态码:${response.statusCode}");
  }
}

void main() {
  fetchData();
}
POST 请求
void postData() async {
  final dioClient = DioClient();
  final response = await dioClient.post(
    "/posts",
    data: {"title": "Flutter", "body": "Hello World", "userId": 1},
  );

  if (response.statusCode == 201) {
    print("数据提交成功:${response.data}");
  } else {
    print("请求失败,状态码:${response.statusCode}");
  }
}

void main() {
  postData();
}

5. 总结

5.1 httpdio 的对比

特性httpdio
功能轻量级,适合简单请求功能强大,支持拦截器、文件上传等
学习曲线
扩展性较低
适用场景小型项目中型和大型项目

5.2 实践建议

  1. 小型项目
    • 使用 http,简单易用。
  2. 中型和大型项目
    • 使用 dio,并通过单例模式封装,统一管理网络请求。

相关文章:

  • 【吾爱出品】[Windows] 透明浏览器V1
  • 【Elasticsearch】监控与管理:集群安全管理
  • Rabbitmq的三个端口区分
  • 如何利用国内镜像从huggingface上下载项目
  • 实现可拖拽的 Ant Design Modal 并保持下层 HTML 可操作性
  • 人工智能(AI)的定义与硬件需求
  • 物理层芯片的Auto-negotiation(自动协商)的详细解释
  • 解决 matplotlib 不支持中文字符
  • C++(23):unreachable
  • 【算法与数据结构】字典树(Trie)详解
  • java爬虫抓取网页搜索数据
  • 蓝桥杯 Java B 组 之树的基础(二叉树遍历)
  • Linux Socket编程:TCP开发指南
  • MoE硬件部署
  • 动态规划从入坟走向入坑
  • Python 和 R机器学习(2)随机森林
  • 通信:Winform(结合C#) TCP服务端
  • 探秘 Python 枚举类型:从基础到实战的深度指南
  • uniapp Flex 布局使用记录
  • CE RED 增加网络安全 添加新网络安全类型
  • 秦洪看盘|指标股发力,A股渐有突破态势
  • 真人秀《幸存者》百万美元奖金,25年间“缩水”近一半
  • 甩掉“肥胖刺客”,科学减重指南来了
  • 2025年度十大IP!IP SH荣膺文化综合类TOP10
  • 宁德时代港股募资预计最高至50亿美元:90%将投向匈牙利项目
  • 历史地理学者成一农重回母校北京大学,担任历史系教授