You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Flutter中基于http包创建通用类管理GET与POST请求

构建Flutter可复用HTTP请求类

下面是一个满足需求的ApiService实现,统一管理HTTP请求,消除冗余代码,同时保持扩展性:

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

class ApiService {
  final String baseUrl;
  final http.Client client;

  // 可传入自定义Client(比如测试时用MockClient),默认用http.Client()
  ApiService({required this.baseUrl, http.Client? client})
      : client = client ?? http.Client();

  // GET请求方法
  Future<Map<String, dynamic>> get(
    String endpoint, {
    Map<String, String>? headers,
    Map<String, String>? queryParams,
  }) async {
    // 拼接完整URL,处理查询参数
    Uri url = Uri.parse('$baseUrl/$endpoint');
    if (queryParams != null) {
      url = url.replace(queryParameters: queryParams);
    }

    // 发送请求
    final response = await client.get(url, headers: _buildHeaders(headers));

    // 统一处理响应
    return _handleResponse(response);
  }

  // POST请求方法,支持JSON body
  Future<Map<String, dynamic>> post(
    String endpoint, {
    Map<String, String>? headers,
    Map<String, dynamic>? body,
  }) async {
    final url = Uri.parse('$baseUrl/$endpoint');
    final requestHeaders = _buildHeaders(headers);
    final encodedBody = body != null ? jsonEncode(body) : null;

    final response = await client.post(
      url,
      headers: requestHeaders,
      body: encodedBody,
    );

    return _handleResponse(response);
  }

  // 构建请求头,默认添加Content-Type: application/json
  Map<String, String> _buildHeaders(Map<String, String>? customHeaders) {
    final defaultHeaders = {'Content-Type': 'application/json'};
    if (customHeaders != null) {
      defaultHeaders.addAll(customHeaders);
    }
    return defaultHeaders;
  }

  // 统一解析响应,处理错误状态码
  Map<String, dynamic> _handleResponse(http.Response response) {
    switch (response.statusCode) {
      case 200:
      case 201:
        return jsonDecode(response.body);
      case 400:
        throw Exception('请求参数错误: ${response.body}');
      case 401:
        throw Exception('未授权,请重新登录');
      case 404:
        throw Exception('请求资源不存在');
      case 500:
        throw Exception('服务器内部错误');
      default:
        throw Exception('请求失败,状态码: ${response.statusCode}');
    }
  }

  // 扩展示例:PUT请求
  Future<Map<String, dynamic>> put(
    String endpoint, {
    Map<String, String>? headers,
    Map<String, dynamic>? body,
  }) async {
    final url = Uri.parse('$baseUrl/$endpoint');
    final requestHeaders = _buildHeaders(headers);
    final encodedBody = body != null ? jsonEncode(body) : null;

    final response = await client.put(
      url,
      headers: requestHeaders,
      body: encodedBody,
    );

    return _handleResponse(response);
  }
}

使用示例

初始化ApiService

// 全局初始化(可以放在main函数或依赖注入中)
final apiService = ApiService(baseUrl: 'https://your-api-base-url.com');

调用GET请求

try {
  final data = await apiService.get(
    'users',
    queryParams: {'page': '1', 'limit': '10'},
    headers: {'Authorization': 'Bearer your-token'},
  );
  // 处理返回的数据
  print(data);
} catch (e) {
  // 处理异常
  print('请求失败: $e');
}

调用POST请求

try {
  final data = await apiService.post(
    'users',
    body: {'name': 'John Doe', 'email': 'john@example.com'},
    headers: {'Authorization': 'Bearer your-token'},
  );
  // 处理返回的数据
  print(data);
} catch (e) {
  // 处理异常
  print('请求失败: $e');
}

关键特性说明

  • 基础URL管理:通过构造函数传入,可灵活切换开发/生产环境地址
  • 请求头统一处理:默认添加Content-Type: application/json,支持自定义请求头覆盖或补充
  • 响应解析统一:集中处理不同状态码的错误,避免重复的错误判断逻辑
  • 扩展性强:新增PUT、DELETE等方法只需复制POST/GET的结构,复用_buildHeaders和_handleResponse方法
  • 可测试性:支持传入自定义http.Client,方便单元测试时使用MockClient模拟请求

内容的提问来源于stack exchange,提问作者Navya Narayanan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 00:15:55