16*:Flutter之dio封装

问题

 

目录

 

预备

 

正文

1:封装网络请求的几个好处:
1、便于统一配置请求参数,如header,公共参数,加密规则等
2、方便调试,日志打印
3、优化代码性能,避免到处滥new对象,构建全局单例
4、简化请求步骤,只暴露需要的响应数据,而对错误的响应统一回调
5、对接口数据的基类封装,简化解析流程

2:调用

import 'package:jh_flutter_demo/http/http_utils.dart';

HttpUtils.PostRequest(APIType.Login,{"userName": _name, "pwd": _pwd}, success: (data) {

}, fail: (code) {

});

3:apis

class APIs {
  //url 前缀
  static const String apiPrefix =
"https://www.fastmock.site/mock/1010b262a743f0b06c565c7a31ee9739/root";
  //登录接口
  static String login = "/login";
}

//接口类型,依次往下加
enum APIType {
  Login,
  GetPage,
}
//使用:APITypeValues[APIType.Login]
const APITypeValues = {
  APIType.Login: "/login",
  APIType.GetPage: "/getPageArrDic"
};

4:dio_utils

import 'dart:convert';

import 'package:dio/dio.dart';
import 'package:connectivity/connectivity.dart';

import 'apis.dart';
import 'log_utils.dart';
import 'error_handle.dart';

const int _connectTimeout = 15000; //15s
const int _receiveTimeout = 15000;
const int _sendTimeout = 10000;

typedef Success<T> = Function(T data);
typedef Fail = Function(int code, String msg);
class DioUtils {
  // default options
  static const String TOKEN = '';

  static Dio _dio;

  // 创建 dio 实例对象
  static Dio createInstance() {
    if (_dio == null) {
      /// 全局属性:请求前缀、连接超时时间、响应超时时间
      var options = BaseOptions(
        /// 请求的Content-Type,默认值是"application/json; charset=utf-8".
        /// 如果您想以"application/x-www-form-urlencoded"格式编码请求数据,
        /// 可以设置此选项为 `Headers.formUrlEncodedContentType`,  这样[Dio]就会自动编码请求体.
//        contentType: Headers.formUrlEncodedContentType, // 适用于post form表单提交
        responseType: ResponseType.json,
        validateStatus: (status) {
          // 不使用http状态码判断状态,使用AdapterInterceptor来处理(适用于标准REST风格)
          return true;
        },
        baseUrl: APIs.apiPrefix,
//        headers: httpHeaders,
        connectTimeout: _connectTimeout,
        receiveTimeout: _receiveTimeout,
        sendTimeout: _sendTimeout,
      );
      _dio = new Dio(options);
    }
    return _dio;
  }

  // 清空 dio 对象
  static clear() {
    _dio = null;
  }

  // 请求,返回参数为 T
  // method:请求方法,Method.POST等
  // path:请求地址
  // params:请求参数
  // success:请求成功回调
  // error:请求失败回调
  static Future request<T>(Method method, String path, dynamic params,
      {Success success, Fail fail}) async {
    try {
      //没有网络
      var connectivityResult = await (new Connectivity().checkConnectivity());
      if (connectivityResult == ConnectivityResult.none) {
        _onError(ExceptionHandle.net_error, '网络异常,请检查你的网络!', fail);
        return;
      }
      Dio _dio = createInstance();
      Response response = await _dio.request(path,
          data: params, options: Options(method: MethodValues[method]));
      if (response != null) {
        if (success != null) {
          success(response.data);
        }
      } else {
        _onError(ExceptionHandle.unknown_error, '未知错误', fail);
      }
    } on DioError catch (e) {
//      LogUtils.print_('请求出错:' + e.toString());
      final NetError netError = ExceptionHandle.handleException(e);
      _onError(netError.code, netError.msg, fail);
    }
  }
}

/// 自定义Header
Map<String, dynamic> httpHeaders = {
  'Accept': 'application/json,*/*',
  'Content-Type': 'application/json',
  'token': DioUtils.TOKEN
};

void _onError(int code, String msg, Fail fail) {
  if (code == null) {
    code = ExceptionHandle.unknown_error;
    msg = '未知异常';
  }
  LogUtils.print_('接口请求异常: code: $code, msg: $msg');
  if (fail != null) {
    fail(code, msg);
  }
}

Map<String, dynamic> parseData(String data) {
  return json.decode(data) as Map<String, dynamic>;
}

enum Method { GET, POST, DELETE, PUT, PATCH, HEAD }
//使用:MethodValues[Method.POST]
const MethodValues = {
  Method.GET: "get",
  Method.POST: "post",
  Method.DELETE: "delete",
  Method.PUT: "put",
  Method.PATCH: "patch",
  Method.HEAD: "head",
};

5:error_handle

import 'dart:io';

import 'package:dio/dio.dart';


class ExceptionHandle {
  static const int success = 200;
  static const int success_not_content = 204;
  static const int unauthorized = 401;
  static const int forbidden = 403;
  static const int not_found = 404;

  static const int net_error = 1000;
  static const int parse_error = 1001;
  static const int socket_error = 1002;
  static const int http_error = 1003;
  static const int timeout_error = 1004;
  static const int cancel_error = 1005;
  static const int unknown_error = 9999;

  static NetError handleException(DioError error) {
    if (error is DioError) {
      if (error.type == DioErrorType.DEFAULT ||
          error.type == DioErrorType.RESPONSE) {
        dynamic e = error.error;
        if (e is SocketException) {
          return NetError(socket_error, '网络异常,请检查你的网络!');
        }
        if (e is HttpException) {
          return NetError(http_error, '服务器异常!');
        }
        if (e is FormatException) {
          return NetError(parse_error, '数据解析错误!');
        }
        return NetError(net_error, '网络异常,请检查你的网络!');
      } else if (error.type == DioErrorType.CONNECT_TIMEOUT ||
          error.type == DioErrorType.SEND_TIMEOUT ||
          error.type == DioErrorType.RECEIVE_TIMEOUT) {
        //  连接超时 || 请求超时 || 响应超时
        return NetError(timeout_error, '连接超时!');
      } else if (error.type == DioErrorType.CANCEL) {
        return NetError(cancel_error, '取消请求');
      } else {
        return NetError(unknown_error, '未知异常');
      }
    } else {
      return NetError(unknown_error, '未知异常');
    }
  }



}

class NetError {
  int code;
  String msg;

  NetError(this.code, this.msg);
}

6:http_utils

import 'package:jh_flutter_demo/jh_common/widgets/jh_progress_hud.dart';

import 'apis.dart';
import 'dio_utils.dart';
import 'log_utils.dart';

typedef Success<T> = Function(T data);
typedef Fail = Function(int code);

class HttpUtils {
  //登录
  static void login<T>(
    parameters, {
    Success success,
    Fail fail,
  }) {
//    DioUtils.request(Method.POST, APIs.login, parameters,
//        success: success, fail: fail);
    post(APIs.login, parameters, success: success, fail: fail);
  }

  //分页加载数据
  static void getNewPageList<T>(
    parameters, {
    Success success,
    Fail fail,
  }) {
    post(APIs.getPage, parameters, success: success, fail: fail);
  }

  //GET
  static void GetRequest<T>(
    APIType apiType,
    parameters, {
    Success success,
    Fail fail,
  }) {
    post(APITypeValues[apiType], parameters, success: success, fail: fail);
  }

  //POST
  static void PostRequest<T>(
    APIType apiType,
    parameters, {
    Success success,
    Fail fail,
  }) {
    post(APITypeValues[apiType], parameters, success: success, fail: fail);
  }

  /********************************* 分割线 ********************************/

  //get 请求
  static void get<T>(
    String url,
    parameters, {
    Success success,
    Fail fail,
  }) {
    _request(Method.GET, url, parameters, success: success, fail: fail);
  }

  //post 请求
  static void post<T>(
    String url,
    parameters, {
    Success success,
    Fail fail,
  }) {
    _request(Method.POST, url, parameters, success: success, fail: fail);
  }

  //_request 请求
  static void _request<T>(
    Method method,
    String url,
    parameters, {
    Success success,
    Fail fail,
  }) {
    /// restful 请求处理
    /// /base/search/hist/:user_id        user_id=27
    /// 最终生成 url 为     /base/search/hist/27
    parameters.forEach((key, value) {
      if (url.indexOf(key) != -1) {
        url = url.replaceAll(':$key', value.toString());
      }
    });
//    //参数处理
//    LogUtils.d("--------- parameters ---------");
//    LogUtils.d("$parameters");

    DioUtils.request(method, url, parameters, success: (result) {
//      LogUtils.d("--------- response ---------");
//      LogUtils.d('$result');
//      LogUtils.print_(result);
      if (result['code'] == 200) {
        if (success != null) {
          success(result);
        }
      } else {
        //其他状态,弹出错误提示信息
        JhProgressHUD.showText(result['msg']);
      }
    }, fail: (code, msg) {
      JhProgressHUD.showError(msg);
      if (fail != null) {
        fail(code);
      }
    });
  }
}

注意

 

引用

1:Flutter - dio 简单封装

2:Flutter网络请求库Dio的封装(单例、动态baseUrl、拦截器)

posted on 2020-12-05 11:34  风zk  阅读(1356)  评论(0编辑  收藏  举报

导航