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); } }); } }
注意