Flutter的网络请求,封装使用直接用就完了

直接上代码,好用点赞,不好用你喷我

拦截器,给head添加token;拦截401相关

import 'dart:convert';

import 'package:dio/dio.dart';
import 'package:yzm_flutter_driver/base/services/auth_service.dart';
import 'package:get/get.dart' as getx;
import 'package:yzm_flutter_driver/network/network_interceptor/repository.dart';

import '../../common/utils/toast.dart';
import '../../routes/app_pages.dart';
import '../base_model/result_base.dart';

/// 请求拦截相关的处理
class NetInterceptor extends Interceptor {
  NetInterceptor();

  @override
  void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
    if (!options.headers.containsKey("token")) {
      final token = AuthService.to.token;
      if (token != null && token.isNotEmpty) {
        options.headers['token'] = token;
      }
    }
    handler.next(options);
  }

  @override
  void onResponse(Response response, ResponseInterceptorHandler handler) {
    int? statusCode = response.statusCode;
    if (statusCode == 200) {
      Map dataMap;
      if (response.data != null) {
        if (response.data is Map<String, dynamic>) {
          dataMap = response.data as Map;
        } else if (response.data is String) {
          dataMap = jsonDecode(response.data) as Map;
        } else {
          dataMap = {'code': 200, 'data': response.data, 'message': 'success'};
        }
        final result = wrapResult(dataMap as Map<String, dynamic>);
      }
    }

    handler.next(response);
  }

  @override
  void onError(DioException err, ErrorInterceptorHandler handler) {
    return handler.next(err);
  }
}

// 首先,你需要定义一个函数来根据数据类型将解析后的数据包装为 Result 对象:
Result<T> wrapResult<T>(Map<String, dynamic> dataMap) {
  return Result<T>(
    code: dataMap['code'],
    info: dataMap['info'],
    data: dataMap['data'], // Adjust this based on your data structure
  );
}
import 'package:dio/dio.dart';
import 'package:yzm_flutter_driver/common/utils/app_log.dart';

/// 统一处理错误信息
String formatError(e) {
  if (e is Response) {
    logger.d(e.toString());
    return e.statusMessage ?? '请求错误';
  }
  if (e is DioException) {
    String message = "";
    if (e.response != null && e.response!.statusCode != null) {
      switch (e.response!.statusCode) {
        case 400:
          message = "请求参数有误"; // signature Attestation of failure
          break;
        case 403:
          message = "请求被拒绝";
          break;
        case 404:
          message = "资源未找到";
          break;
        case 405:
          message = "请求方式不被允许";
          break;
        case 408:
          message = "请检查网络是否可用,再行尝试"; // 请求超时
          break;
        case 422:
          message = "请求语义错误";
          break;
        case 500:
          message = "服务器逻辑错误";
          break;
        case 502:
          message = "服务器网关错误";
          break;
        case 504:
          message = "服务器网关超时";
          break;
        default:
          message = "请求异常,请稍后再试";
      }
      return message;
    } else {
      switch (e.type) {
        case DioExceptionType.connectionTimeout:
          message = "连接超时";
          break;
        case DioExceptionType.sendTimeout:
          message = "请求超时";
          break;
        case DioExceptionType.receiveTimeout:
          message = "响应超时";
          break;
        case DioExceptionType.connectionError:
          message = "当前网络不可用,请检查你的网络...";
          break;
        default:
          if (e.message != null && e.message!.isNotEmpty) {
            message = e.message!;
          } else {
            message = "请求异常";
          }
          break;
      }
      return message;
    }
  } else if (e is TypeError) {
    return "数据解析类型转换异常";
  }
  return "未知错误";
}

网络请求封装

import 'package:json_annotation/json_annotation.dart';

@JsonSerializable()
class Result<T> {
  @JsonKey(name: 'code')
  int code;
  @JsonKey(name: 'msg')
  String? info;
  @JsonKey(name: 'data')
  dynamic data;

  Result({
    required this.code,
    required this.info,
    required this.data,
  });

  factory Result.fromJson(Map<String, dynamic> json) {
    return Result(
      code: json['code'] as int,
      info: json['msg'] == null ? '' : json['msg'] as String,
      data: json['data'] as dynamic,
    );
  }

  Map<String, dynamic> toJson() {
    return {
      'code': code,
      'msg': info,
      'data': data,
    };
  }
}

class YzmError {
  late int errorCode;
  late String errorMsg;
}
class ApiClient {
  late Dio _dio;
  String baseUrl = BaseConstants.BASE_URL;
  // 私有构造函数
  ApiClient._internal() {
    _dio = Dio(BaseOptions(
         
        sendTimeout: const Duration(seconds: 10),
        connectTimeout: const Duration(seconds: 10),
        receiveTimeout: const Duration(seconds: 10)))
      ..interceptors.addAll([
        LogInterceptor(
          requestBody: true,
          responseBody: true,
        ),
        NetInterceptor(),
      ]); // 创建Dio实例
  }

  static final ApiClient _instance = ApiClient._internal();

  // 工厂方法返回单例实例
  factory ApiClient() {
    return _instance;
  }

  /// POST请求
  Future<void> postRequest(
      {required String url,
      required Map<String, dynamic> request,
      required Function(Result) reqeustSuccess,
      required Function(YzmError) requestFail,
      Map<String, dynamic> headers = const <String, dynamic>{}}) async {
    const extra = <String, dynamic>{};
    final queryParameters = <String, dynamic>{}; 
    final data = <String, dynamic>{};
    data.addAll(request);
    Result value = Result(code: 0, info: "info", data: Map());
    try {
      final result = await _dio
          .fetch<Map<String, dynamic>>(_setStreamType<Result<String>>(Options(
        method: 'POST',
        headers: headers,
        extra: extra,
      )
              .compose(
                _dio.options,
                url,
                queryParameters: queryParameters,
                data: json.encode(data),
              )
              .copyWith(
                  baseUrl: _combineBaseUrls(
                _dio.options.baseUrl,
                baseUrl,
              ))));

      _requestInfo(value, result, reqeustSuccess, requestFail);
    } catch (e) {
      // e= 网络错误,解析数据异常,其它
      YzmError error = YzmError();
      error.errorCode = 0;
      error.errorMsg = formatError(e);
      requestFail(error);
      return;
    }
  }

 

  /// url合并
  String _combineBaseUrls(
    String dioBaseUrl,
    String? baseUrl,
  ) {
    if (baseUrl == null || baseUrl.trim().isEmpty) {
      return dioBaseUrl;
    }

    final url = Uri.parse(baseUrl);

    if (url.isAbsolute) {
      return url.toString();
    }

    return Uri.parse(dioBaseUrl).resolveUri(url).toString();
  }

  /// dio的参数解析
  RequestOptions _setStreamType<T>(RequestOptions requestOptions) {
    if (T != dynamic &&
        !(requestOptions.responseType == ResponseType.bytes ||
            requestOptions.responseType == ResponseType.stream)) {
      if (T == String) {
        requestOptions.responseType = ResponseType.plain;
      } else {
        requestOptions.responseType = ResponseType.json;
      }
    }
    return requestOptions;
  }

  YzmError _requestError(Result value) {
    YzmError error = YzmError();
    error.errorCode = value.code;
    error.errorMsg = value.info ?? "";
    return error;
  }

  // 网络请求返回信息通用
  _requestInfo(
    value,
    result,
    Function(Result) reqeustSuccess,
    Function(YzmError) requestFail,
  ) {
    // 网络请求错误相关异常
    if (result.statusCode != 200) {
      YzmError error = YzmError();
      error.errorCode = 0;
      DioException dioException =
          DioException(requestOptions: result.requestOptions, response: result);
      error.errorMsg = formatError(dioException);
      requestFail(error);
      return;
    }
    // 解析数据
    value = Result.fromJson(result.data!);
    // 返回的业务异常
    if (value.code != 200) {
      requestFail(_requestError(value));
      return;
    }
    // 返回成功
    reqeustSuccess(value);
  }
}
class ApiUrl {
 
  static const String getsxxxx= "/system/xxx/xxx";
}

使用

  chooseRole(String type) async {
    Toast.showLoading();
    Map<String, dynamic> request = {};
    request['xx'] = type;
    await ApiClient().postRequest(
      url: ApiUrl.xxx,
      request: request,
      reqeustSuccess: (result) {
        Toast.hideLoading(); 
      },
      requestFail: (a) {
        Toast.hideLoading();
        BotToast.showText(text: a.errorMsg);
      },
    );
  }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值