用了两年的flutter,有了一些心得,不虚头巴脑,只求实战有用,以供学习或使用flutter的小伙伴参考,学习尚浅,如有不正确的地方还望各路大神指正,以免误人子弟,在此拜谢(原创不易,转发请标注来源和作者) 注意:无特殊说明,flutter版本为3。0 上篇总结了api的组织结构,这一篇我们探讨一下Flutter常用请求库Dio的使用和封装。一。dio 一般http请求我们要关注的点有如下几个: 访问路径,请求方式,请求头部,请求参数,超时时间,返回结果,返回类型等。 注:(对httphttps协议不太明白的,需要补课的童鞋可以去看下基础教程https:www。runoob。comhttphttptutorial。html) 首先看下dio可配置的参数: BaseOptions({ String?method, int?connectTimeout, int?receiveTimeout, int?sendTimeout, StringbaseUrl, MapString,dynamic?queryParameters, MapString,dynamic?extra, MapString,dynamic?headers, ResponseType?responseTypeResponseType。json, String?contentType, ValidateStatus?validateStatus, bool?receiveDataWhenStatusError, bool?followRedirects, int?maxRedirects, RequestEncoder?requestEncoder, ResponseDecoder?responseDecoder, ListFormat?listFormat, this。setRequestContentTypeWhenNoPayloadfalse, }) 除了基础配置dio还提供了拦截器interceptors,适配器httpClientAdapter,请求方法get,post,delete,put,patch,download等基础的封装,方便我们使用。二。Http基础类 classHttp{ 定义各类超时时间 staticconstintCONNECTTIMEOUT10000;默认设置10s超时 staticconstintRECEIVETIMEOUT3000; staticconstintSENDTIMEOUT3000; Dio?dio; staticHttpinstanceHttp。internal(); 1。internal()获取Dio实例的方法,主要是配置适配器Http。internal(){ dioDio(); dio。httpClientAdapterDefaultHttpClientAdapter() 。。onHttpClientCreate(HttpClientc,lient){ client。idleTimeoutDuration(milliseconds:CONNECTTIMEOUT); }; 添加错误统一处理拦截器 dio!。interceptors。add(ErrorInterceptor()); 添加日志拦截器 dio!。interceptors。add(DioLogInterceptor()); 2。post方法源码示例 Futurepost( Stringpath,{ requiredStringbaseUrl, MapString,dynamic?params, MapString,dynamic?headers, data, Options?options, CancelToken?cancelToken, })async{ OptionsrequestOptionsoptions??Options(); requestOptions。baseUrlbaseUrl; MapString,dynamic?authorizationheaders??getAuthorizationHeader(); if(authorization!null){ requestOptionsrequestOptions。copyWith(headers:authorization); } dio!。options。baseUrlbaseUrl; dio!。options。connectTimeoutCONNECTTIMEOUT; dio!。options。receiveTimeoutRECEIVETIMEOUT; dio!。options。sendTimeoutSENDTIMEOUT; varresponse; vartimeoutDuration(milliseconds:dio!。options。connectTimeout); cancelTokenCancelToken(); vartTimer(timeout,(){ if(responsenull){ cancelToken!。cancel(); } }); response awaitdio!。post(path,data:data,queryParameters:params,options:requestOptions,cancelToken:cancelToken); t。cancel(); returnresponse。data; } cancelToken是dio提供的一个非常有用的东西,可以主动在返回超时时候,主动结束请求,并触发DioErrorType。cancel的错误事件。 三。httpUtils加强封装1。添加是否等待处理 还以post为例,我们定义一个方法调用http的基础类 staticFuturepost(Stringpath,{data,requiredStringbaseUrl, MapString,dynamic?params, Options?options, CancelToken?cancelToken, boolshowLoadingfalse} 这里加了一个参数showLoading,在我们实际开发过程中,有一些操作要阻断用户操作,等待接口请求,一些是不需要用户感知的请求,我们可以在所有api中,默认添加该参数为false,有必要阻断用户的时候调用的时候将该参数设置成为true,举个例子如下: 忘记密码 staticFutureforgetPassword(dynamicparam,{boolshowLoadingfalse})async{ varresawaitHttpUtils。post(forgetPassword,data:param,baseUrl:xxxshowLoading:showLoading); returnres; } 当判断需要loading的时候 if(showLoading){ showLoadingDialog(); } 作者使用的是fluttersmartdialog:4。5。37,使用比较简单,你可以自己去封装所需要的loading样式。2。定义统一返回类型 classApiResponseimplementsException{ String?errorMsg; String?msg; int?code; T?data; ApiResponse(this。msg); ApiResponse。error(Stringmsg){ toastMsg(msg); } override StringtoString(){ returnMsg:msgerrorMsg:errorMsgData:data; } ApiResponse。fromJson(MapString,dynamicjson){ msgjson〔msg〕; errorMsgjson〔errorMsg〕; codejson〔code〕; datajson〔data〕; } MapString,dynamictoJson(){ finalMapString,dynamicdatanewMapString,dynamic(); data〔msg〕this。msg; data〔errorMsg〕this。errorMsg; data〔code〕this。code; data〔data〕this。data; returndata; } } 3。返回处理 判断后台返回的正确code,则返回结果,完结后清除loading状态。 源码如下 classHttpUtils{staticFuturepost(Stringpath, {data, requiredStringbaseUrl, MapString,dynamic?params, Options?options, CancelToken?cancelToken, boolshowLoadingfalse, boolcanNullfalse, Function(Object?)?onError, boolerrorToasttrue, boolisolatetrue})async{ if(showLoading){ showLoadingDialog(path:path); }returnHttp() 。post( path, baseUrl:baseUrl, data:data, params:params, options:options, cancelToken:cancelToken, ) 。then((value){ varresultApiResponse。fromJson(valueisMap?value:jsonDecode(value)); if(result。code2000){ returnresult。data; }else{ throwApiResponse(result。msg!); } })。onError((error,stackTrace){ if(onError!null){ onError(error); } if(errorisRemoteError){ toastMsg(网络连接失败,displayType:SmartToastType。last); }elseif(errorisApiResponse){ toastMsg(error。msg!); }else{ toastMsg(未知错误); } throwException(error。toString()); })。whenComplete((){ if(showLoading){ SmartDialog。dismiss(); } }); }