0


flutter dio 请求封装(空安全)

一、添加依赖

dio:^5.3.2

二、请求封装

classHttpHelper{staticDio? mDio;staticBaseOptions? options;staticHttpHelper? httpHelper;CancelToken cancelToken =CancelToken();staticconstString GET ='get';staticconstString POST ='post';staticconstString PUT ='put';staticconstString PATCH ='patch';staticconstString DELETE ='delete';staticHttpHelper?get instance =>getInstance();staticDio?get dio =>getDio();staticHttpHelper?getInstance(){
    httpHelper ??=HttpHelper();return httpHelper;}staticDio?getDio(){final token =GetStorage().read('token');finalMap<String,dynamic> headerMap ={};if(token !=null){
      headerMap.putIfAbsent("Authorization",()=>"Bearer $token");}

    options =BaseOptions(//请求基地址,可以包含子路径
      baseUrl:Api.BASE_URL,//连接服务器超时时间,单位是毫秒.
      connectTimeout:constDuration(seconds:10),//2.x中为接收数据的最长时限
      receiveTimeout:constDuration(seconds:5),//Http请求头.
      headers: headerMap,// 请求的Content-Type,默认值是"application/json; charset=utf-8".//   /// 如果您想以"application/x-www-form-urlencoded"格式编码请求数据,//   /// 可以设置此选项为 `Headers.formUrlEncodedContentType`,  这样[Dio]//   /// 就会自动编码请求体.
      contentType:Headers.jsonContentType,/// [responseType] 表示期望以那种格式(方式)接受响应数据。/// 目前 [ResponseType] 接受三种类型 `JSON`, `STREAM`, `PLAIN`.////// 默认值是 `JSON`, 当响应头中content-type为"application/json"时,dio 会自动将响应内容转化为json对象。/// 如果想以二进制方式接受响应数据,如下载一个二进制文件,那么可以使用 `STREAM`.////// 如果想以文本(字符串)格式接收响应数据,请使用 `PLAIN`.
      responseType:ResponseType.json,);

    mDio =Dio(options);
    mDio?.interceptors.add(interceptorsWrapper());

    mDio?.httpClientAdapter =IOHttpClientAdapter(
      createHttpClient:(){final client =HttpClient();// Config the client.
        client.findProxy =(uri){// Forward all request to proxy "localhost:8888".// Be aware, the proxy should went through you running device,// not the host platform.return'PROXY 192.168.0.191:8089';};// You can also create a new HttpClient for Dio instead of returning,// but a client must being returned here.return client;},);return mDio;}staticInterceptorsWrapperinterceptorsWrapper(){returnInterceptorsWrapper(onRequest:(options, handler){// Do something before request is sentreturn handler.next(options);//continue// 如果你想完成请求并返回一些自定义数据,你可以resolve一个Response对象 `handler.resolve(response)`。// 这样请求将会被终止,上层then会被调用,then中返回的数据将是你的自定义response.//// 如果你想终止请求并触发一个错误,你可以返回一个`DioError`对象,如`handler.reject(error)`,// 这样请求将被中止并触发异常,上层catchError会被调用。}, onResponse:(response, handler){// Do something with response datareturn handler.next(response);// continue// 如果你想终止请求并触发一个错误,你可以 reject 一个`DioError`对象,如`handler.reject(error)`,// 这样请求将被中止并触发异常,上层catchError会被调用。}, onError:(DioError e, handler){// Do something with response errorif(e.response !=null){if(e.response?.statusCode ==401){ToastMsg.show("当前登录已过期,请重新登录!");Future.delayed(constDuration(milliseconds:1000),(){Get.offAllNamed(AppRoutes.LOGIN);});}elseif(e.response?.statusCode ==403){ToastMsg.show("暂无权限访问,请联系管理员!");}else{ToastMsg.show("系统内部异常!");}}return handler.next(e);//continue// 如果你想完成请求并返回一些自定义数据,可以resolve 一个`Response`,如`handler.resolve(response)`。// 这样请求将会被终止,上层then会被调用,then中返回的数据将是你的自定义response.});}///Get请求Future<BaseRes<T>> getHttp<T>(String url, parameters,{loading =true})async{returnawait getResponse<T>(url, method: GET, parameters: parameters,loading:loading);}Future<BaseRes<T>> postHttp<T>(String url, parameters,{loading =true})async{///定义请求参数
    parameters = parameters ??<String,dynamic>{};returnawait getResponse<T>(url, method: POST, parameters: parameters,loading:loading);}Future<BaseRes<T>> putHttp<T>(String url, parameters,{loading =true})async{///定义请求参数
    parameters = parameters ??<String,dynamic>{};returnawait getResponse<T>(url, method: PUT, parameters: parameters,loading:loading);}Future<BaseRes<T>> deleteHttp<T>(String url, parameters,{loading =true})async{///定义请求参数
    parameters = parameters ??<String,dynamic>{};returnawait getResponse<T>(url, method: DELETE, parameters: parameters,loading:loading);}/*
   * 下载文件
   */downloadFile(urlPath, savePath, onReceiveProgress)async{Response? response;try{
      response =await dio?.download(urlPath, savePath,
          onReceiveProgress: onReceiveProgress);}onDioErrorcatch(e){formatError(e);}return response?.data;}Future<BaseRes<T>> getResponse<T>(String url,{
    required String method,
    parameters,
    loading,})async{//这里指定response自动转成map,不指定的话有可能是String类型Response<Map<String,dynamic>>? response;if(loading){ToastMsg.showLoading();}switch(method){case GET:
        response =await dio?.get(url,
            queryParameters: parameters ??<String,dynamic>{});break;case PUT:
        response =await dio?.put(url,
            queryParameters: parameters ??<String,dynamic>{});break;case DELETE:
        response =await dio?.delete(url,
            queryParameters: parameters ??<String,dynamic>{});break;default:
        response =await dio?.post(url, data: parameters ??<String,dynamic>{});break;}if(loading){ToastMsg.cancelLoading();}//200代表网络请求成功if(response?.statusCode ==200){/// 将后台的data字段转成自己想要的数据/数据集,code根据后端实际返回进行判断访问结果BaseRes<T> bean =BaseRes.fromJson(response?.data);return bean;}elseif(response?.statusCode ==401){ToastMsg.show("当前登录已过期,请重新登录!");Future.delayed(constDuration(milliseconds:1000),(){Get.offAllNamed(AppRoutes.LOGIN);});}elseif(response?.statusCode ==403){ToastMsg.show("暂无权限访问,请联系管理员!");}else{ToastMsg.show("系统内部异常!");}throwException('${response?.statusCode}+${response?.statusMessage}');}voidformatError(DioError e){print(e.message);}/*
   * 取消请求
   * 同一个cancel token 可以用于多个请求,当一个cancel token取消时,所有使用该cancel token的请求都会被取消。
   */voidcancelRequests(CancelToken token){
    token.cancel("cancelled");}}

三、封装统一返回类

@JsonSerializable()classBaseRes<T>{BaseRes(this.msg,this.code,this.data);

  late String msg;
  late int code;
  late T data;BaseRes.fromJson(Map<String,dynamic>? json){if(json?['data']!=null&& json?['data']!='null'){
      data =JsonConvert.fromJsonAsT<T>(json?['data'])asT;}
    msg = json?['msg'];
    code = json?['code'];}Map<String,dynamic>toJson(){finalMap<String,dynamic> data =<String,dynamic>{};if(this.data !=null){
      data['data']=this.data;}
    data['code']=this.code;
    data['msg']=this.msg;return data;}}

四、使用

// Entity类使用的是JsonToDartBeanAction生成BaseRes<UserInfoEntity>? res =awaitHttpHelper.instance?.getHttp(Api.GET_USER_INGO,null,loading:false);if(res?.code ==200&& res?.data !=null){
      state.userInfo = res!.data.obs;}
标签: flutter

本文转载自: https://blog.csdn.net/weixin_45444807/article/details/133773586
版权归原作者 程序猿小张丶 所有, 如有侵权,请联系我们删除。

“flutter dio 请求封装(空安全)”的评论:

还没有评论