文章 64
评论 33
浏览 142909
flutter 使用Dio 4.x封装工具类,支持空安全.

flutter 使用Dio 4.x封装工具类,支持空安全.

记录一下, Dio 高版本4.x支持空安全封装的工具包,本文不全!

一、引入依赖 Dio

dio: ^4.0.0

此时使用最新版本dio,时间:2021-7-01

二、创建Dio的单例实例:

import 'package:dio/dio.dart';

class DioHttpClient {
  static const int _DEFAULT_CONNECT_TIMEOUT = 60 * 1000;
  static const int _DEFAULT_SEND_TIMEOUT = 60 * 1000;
  static const int _DEFAULT_RECEIVE_TIMEOUT = 60 * 1000;

  final Map<String, Dio> _mClientMap = <String, Dio>{};

  DioHttpClient._internal();

  static final DioHttpClient _instance = DioHttpClient._internal();

  factory DioHttpClient.getInstance() => _instance;

  Dio getClient(String baseUrl,
      {BaseOptions? newOptions, List<Interceptor>? interceptors}) {
    Dio client =
        _mClientMap[baseUrl] ?? _createDioClient(baseUrl, options: newOptions);
    if (interceptors != null) {
      client.interceptors.addAll(interceptors);
    }
    return client;

  }

  Dio _createDioClient(String baseUrl, {BaseOptions? options}) {
    if (options == null) {
      options = createOptions(baseUrl);
    }
    return Dio(options);
  }

  static BaseOptions createOptions(String baseUrl,
      {Map<String, dynamic>? headers, Map<String, dynamic>? queryParameters}) {
    return BaseOptions(
      connectTimeout: _DEFAULT_CONNECT_TIMEOUT,
      sendTimeout: _DEFAULT_SEND_TIMEOUT,
      receiveTimeout: _DEFAULT_RECEIVE_TIMEOUT,
      baseUrl: baseUrl,
      responseType: ResponseType.json,
      validateStatus: (status) {
        return true;
      },
      headers: headers,
      queryParameters: queryParameters,
    );
  }

  void release() {
    _mClientMap.clear();
  }
}

三、创建工具类发起各种乱遭的请求:

import 'package:demo01/utils/net/authorization_interceptor.dart';
import 'package:dio/dio.dart';

import 'dio_client.dart';
import 'log_interceptor.dart';

class PrettyHttp {
  static const String GET = 'get';
  static const String POST = 'post';
  static const String DELETE = 'delete';
  static const String PUT = 'put';
  static const String HEAD = 'head';
  static const String PATCH = 'patch';

  static const String BASE_URL = "https://api.moyutang.fun";

  static Interceptor logInterceptor = PrettyLogInterceptor();
  static Interceptor authInterceptor = AuthorizationInterceptor(beAuth: true);
  static Interceptor unAuthInterceptor =
      AuthorizationInterceptor(beAuth: false);

  static Future<Map<String, dynamic>> http(
    String method,
    String pathUrl, {
    String? baseUrl: BASE_URL,
    bool beAuth: true,
    Map<String, dynamic>? reqParams,
    Map<String, dynamic>? data,
    Map<String, dynamic>? headers,
    Function(Map<String, dynamic>)? onSuccess,
    Function(String)? onError,
  }) async {
    reqParams = reqParams ?? {};

    try {
      BaseOptions options =
          DioHttpClient.createOptions(baseUrl!, headers: headers);

      var dioClient = DioHttpClient.getInstance().getClient(baseUrl,
          newOptions: options,
          interceptors: [
            logInterceptor,
            beAuth ? authInterceptor : unAuthInterceptor
          ]);
      Response response;
      // Response<Map<String, dynamic>> response;

      switch (method) {
        case GET:
          response = await dioClient.get(pathUrl, queryParameters: reqParams);
          break;
        case POST:
          response = await dioClient.post(
            pathUrl,
            queryParameters: reqParams,
            data: data,
          );
          break;
        case PUT:
          response = await dioClient.put(pathUrl, queryParameters: reqParams);
          break;
        case DELETE:
          response =
              await dioClient.delete(pathUrl, queryParameters: reqParams);
          break;
        case PATCH:
          response = await dioClient.patch(pathUrl, queryParameters: reqParams);
          break;
        case HEAD:
          response = await dioClient.head(pathUrl, queryParameters: reqParams);
          break;
        default:
          response = await dioClient.get(pathUrl, queryParameters: reqParams);
          break;
      }

      if (onSuccess != null) {
        onSuccess(response.data!);
      }
      return Future.value(response.data);
    } catch (e) {
      if (onError != null) {
        onError(e.toString());
      }
      return Future.error(e);
    }
  }

  static Future<Map<String, dynamic>> get(String pathUrl,
      {String? baseUrl,
      bool beAuth: true,
      Map<String, dynamic>? reqParams,
      Map<String, dynamic>? headers,
      Function(Map<String, dynamic>)? onSuccess,
      Function(String)? onError}) async {
    reqParams = reqParams ?? {};
    baseUrl = baseUrl ?? BASE_URL;
    return http(GET, pathUrl,
        baseUrl: baseUrl,
        beAuth: beAuth,
        reqParams: reqParams,
        headers: headers,
        onSuccess: onSuccess,
        onError: onError);
  }

  static Future<Map<String, dynamic>> post(String pathUrl,
      {String? baseUrl,
      bool beAuth: true,
      Map<String, dynamic>? reqParams,
      Map<String, dynamic>? data,
      Map<String, dynamic>? headers,
      Function(Map<String, dynamic>)? onSuccess,
      Function(String)? onError}) async {
    reqParams = reqParams ?? {};
    baseUrl = baseUrl ?? BASE_URL;
    return http(POST, pathUrl,
        baseUrl: baseUrl,
        beAuth: beAuth,
        reqParams: reqParams,
        data: data,
        headers: headers,
        onSuccess: onSuccess,
        onError: onError);
  }

  static Future<Map<String, dynamic>> put(String pathUrl,
      {String? baseUrl,
      bool beAuth: true,
      Map<String, dynamic>? reqParams,
      Map<String, dynamic>? headers,
      Function(Map<String, dynamic>)? onSuccess,
      Function(String)? onError}) async {
    reqParams = reqParams ?? {};
    baseUrl = baseUrl ?? BASE_URL;
    return http(PUT, pathUrl,
        baseUrl: baseUrl,
        beAuth: beAuth,
        reqParams: reqParams,
        headers: headers,
        onSuccess: onSuccess,
        onError: onError);
  }

  static Future<Map<String, dynamic>> delete(String pathUrl,
      {String? baseUrl,
      bool beAuth: true,
      Map<String, dynamic>? reqParams,
      Map<String, dynamic>? headers,
      Function(Map<String, dynamic>)? onSuccess,
      Function(String)? onError}) async {
    reqParams = reqParams ?? {};
    baseUrl = baseUrl ?? BASE_URL;
    return http(DELETE, pathUrl,
        baseUrl: baseUrl,
        beAuth: beAuth,
        reqParams: reqParams,
        headers: headers,
        onSuccess: onSuccess,
        onError: onError);
  }

  static Future<Map<String, dynamic>> patch(String pathUrl,
      {String? baseUrl,
      bool beAuth: true,
      Map<String, dynamic>? reqParams,
      Map<String, dynamic>? headers,
      Function(Map<String, dynamic>)? onSuccess,
      Function(String)? onError}) async {
    reqParams = reqParams ?? {};
    baseUrl = baseUrl ?? BASE_URL;
    return http(PATCH, pathUrl,
        baseUrl: baseUrl,
        beAuth: beAuth,
        reqParams: reqParams,
        headers: headers,
        onSuccess: onSuccess,
        onError: onError);
  }

  static Future<Map<String, dynamic>> head(String pathUrl,
      {String? baseUrl,
      bool beAuth: true,
      Map<String, dynamic>? reqParams,
      Map<String, dynamic>? headers,
      Function(Map<String, dynamic>)? onSuccess,
      Function(String)? onError}) async {
    reqParams = reqParams ?? {};
    baseUrl = baseUrl ?? BASE_URL;
    return http(HEAD, pathUrl,
        beAuth: beAuth,
        baseUrl: baseUrl,
        reqParams: reqParams,
        headers: headers,
        onSuccess: onSuccess,
        onError: onError);
  }
}

四、创建各种拦截器实现各种功能:

import 'package:dio/dio.dart';

class PrettyLogInterceptor extends Interceptor {
  PrettyLogInterceptor({
    this.request = true,
    this.requestHeader = true,
    this.requestBody = false,
    this.responseHeader = true,
    this.responseBody = false,
    this.error = true,
  });

  /// Print request [Options]
  bool request;

  /// Print request header [Options.headers]
  bool requestHeader;

  /// Print request data [Options.data]
  bool requestBody;

  /// Print [Response.data]
  bool responseBody;

  /// Print [Response.headers]
  bool responseHeader;

  /// Print error message
  bool error;

  @override
  void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
    _printRequest(options);
    super.onRequest(options, handler);
  }

  @override
  void onError(DioError? err, ErrorInterceptorHandler handler) {
    if (err != null) {
      print('*** DioError ***:');
      print('uri: ${err.requestOptions.uri}');
      print('$err');
      if (err.response != null) {
        _printResponse(err.response!);
      }
      print('');
    }
    super.onError(err!, handler);
  }

  void _printRequest(RequestOptions options) async {
    print('*** Request ***');
    _printKV('uri', options.uri);

    if (request) {
      _printKV('method', options.method);
      _printKV('responseType', options.responseType.toString());
      _printKV('followRedirects', options.followRedirects);
      _printKV('connectTimeout', options.connectTimeout);
      _printKV('receiveTimeout', options.receiveTimeout);
      _printKV('extra', options.extra);
    }
    if (requestHeader) {
      print('headers:');
      options.headers.forEach((key, v) => _printKV(' $key', v));
    }
    if (requestBody) {
      print('data:');
      _printAll(options.data);
    }
    print('');
  }

  void _printResponse(Response response) {
    _printKV('uri', response.requestOptions.uri);
    if (responseHeader) {
      _printKV('statusCode', response.statusCode.toString());
      if (response.isRedirect == true) {
        _printKV('redirect', response.realUri);
      }
      if (response.headers != null) {
        print('headers:');
        response.headers.forEach((key, v) => _printKV(' $key', v.join(',')));
      }
    }
    if (responseBody) {
      print('Response Text:');
      _printAll(response.toString());
    }
    print('');
  }

  void _printKV(String key, Object v) {
    print('$key: $v');
  }

  void _printAll(msg) {
    msg.toString().split('\n').forEach(print);
  }
}
import 'package:demo01/utils/get_store_util.dart';
import 'package:demo01/utils/net/dio_client.dart';
import 'package:demo01/utils/net/pretty_http.dart';
import 'package:dio/dio.dart';

class AuthorizationInterceptor extends Interceptor {
  late bool beAuth;

  AuthorizationInterceptor({required this.beAuth});

  /*@override
  void onResponse(Response response, ResponseInterceptorHandler handler) {
    super.onResponse(response, handler);

    /// 定时刷新token
    if (response.statusCode == 401) {
      Dio _dio = DioHttpClient.getInstance()
          .getClient(response.requestOptions.baseUrl,);

      /// 锁住
      _dio.interceptors.requestLock.lock();
      _dio.interceptors.responseLock.lock();

      /// 获取新的token
      PrettyHttp.post(
        "/api/login?terminal=WEB",
        beAuth: false,
        data: {"phone": "15896272531", "password": "111111"},
      ).then((value) {
        StoreUtils.store.write("user", value);
      }).whenComplete(() {

        _dio.
        _dio.unlock();
        PrettyHttp.http(
          response.requestOptions.method,
          response.requestOptions.path,
          data: response.requestOptions.data,
          reqParams: response.requestOptions.queryParameters,
        );
      });
    }
  }
*/
  @override
  void onRequest(
      RequestOptions options, RequestInterceptorHandler handler) async {
    super.onRequest(options, handler);
    if (beAuth) {
      if (!StoreUtils.store.hasData("user")) {
        PrettyHttp.post(
          "/api/login?terminal=WEB",
          beAuth: false,
          data: {"phone": "15896272531", "password": "111111"},
        ).then((value) {
          StoreUtils.store.write("user", value);
          options.headers['Authorization'] = value['token'];
        });
      } else {
        options.headers['Authorization'] =
            "Bearer ${StoreUtils.store.read("user")['token']}";
      }
    }
  }
}

哈哈哈哈哈哈哈嗝~

取消