問題
目錄
預備
正文
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); } }); } }
注意