美文网首页Flutter相关js css html
Flutter怎么搭建一套健壮可靠的网络框架

Flutter怎么搭建一套健壮可靠的网络框架

作者: 码农朱同学 | 来源:发表于2022-08-02 15:22 被阅读0次

    Flutter怎么搭建一套健壮可靠的网络框架

    网络框架的搭建

    所需依赖库

      dio: ^4.0.0 # 网络框架
      connectivity: ^3.0.6 # 网络框架相关
      crypto: ^3.0.1 #加密库
    

    具体实现

    NetBaseRequest类对外暴露的方法

    abstract class NetBaseRequest{
       request(NetData data);
       download(NetData data,{Function(int,int)? progressCallback});
       upload(NetData data,{Function(int,int)? sendProgressCallback});
       cancelRequest({NetCancelToken? token});
    }
    

    对NetBaseRequest类方法的具体实现

    class NetRequest extends NetBaseRequest {
      late Dio dio;
      late NetCancelToken _cancelToken;
    
      NetRequest() {
        dio = Dio();
        _cancelToken = NetCancelToken();
        dio.interceptors.add(NetCommonInterceptor());
        dio.interceptors.addAll(NetWorkManger().interceptors);
        if (NetWorkManger().isPrintLog) {
          dio.interceptors.add(LogInterceptor(
              requestBody: true,
              responseBody: true,
              logPrint: (value) {
                print(value);
              }));
          (dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate =  (HttpClient client) {
            client.badCertificateCallback = (X509Certificate cert, String host, int port) =>true;
            return client;
          };
        }
      }
    
      ///下载
      @override
      Future<NetData> download(NetData data,
          {Function(int, int)? progressCallback}) async {
        dio.options = _initOptions(data);
        Response response = await dio.download(data.url, data.downloadFilePath,
            cancelToken: data.cancelToken ?? _cancelToken,
            queryParameters: data.params,
            onReceiveProgress: progressCallback);
        return _responseData(data, response);
      }
    
      BaseOptions _initOptions(NetData data) {
        BaseOptions baseOptions = BaseOptions();
        baseOptions.contentType = data.contentType;
        baseOptions.connectTimeout = data.connectTimeOut;
        baseOptions.receiveTimeout = data.readTimeout;
        baseOptions.headers = data.header;
        baseOptions.responseType = ResponseType.json;
        _addDioProxy(data);
        return baseOptions;
      }
    
      @override
      Future<NetData> request(NetData data) async {
        dio.options = _initOptions(data);
        try {
          switch (data.requestType) {
            case RequestType.GET:
              return await _requestGet(data);
            case RequestType.POST:
              return await _requestPost(data);
          }
        } on DioError catch (e) {
          var response = e.response;
          if (response != null) {
            if (response.data != null) {
              data.resultStatus = ResultStatus.success;
              data.resultData = response.data;
              NetWorkManger().responseInterceptor?.responseInterceptor(data);
              return data;
            }
          }
          _requestError(data);
          return data;
        }
      }
    
      ///get网络请求
      _requestGet(NetData data) async {
        Response response;
        if (data.params == null) {
          response = await dio.get(data.url,
              cancelToken: data.cancelToken ?? _cancelToken);
        } else {
          response = await dio.get(data.url,
              queryParameters: data.params,
              cancelToken: data.cancelToken ?? _cancelToken);
        }
        return _responseData(data, response);
      }
    
      ///post网络请求
      _requestPost(NetData data) async {
        Response response;
        if (data.params == null) {
          response = await dio.post(data.url,
              cancelToken: data.cancelToken ?? _cancelToken);
        } else {
          response = await dio.post(data.url,
              data: data.params, cancelToken: data.cancelToken ?? _cancelToken);
        }
        return _responseData(data, response);
      }
    
      ///文件上传
      @override
      upload(NetData data, {Function(int, int)? sendProgressCallback}) async {
        dio.options = _initOptions(data);
        if (data.uploadMap.isNotEmpty) {
          data.resultStatus = ResultStatus.processing;
          Map<String, dynamic> fileMap = {};
          data.uploadMap.forEach((key, value) {
            fileMap[key] =
                MultipartFile.fromFile(value, filename: getFileName(value));
          });
          FormData formData = FormData.fromMap(fileMap);
          Response response = await dio.post(data.url,
              data: formData,
              queryParameters: data.params,
              onSendProgress: sendProgressCallback,
              cancelToken: data.cancelToken ?? _cancelToken);
          return _responseData(data, response);
        }
      }
    
      ///返回数据解析
      _responseData(NetData data, Response response) {
        try {
          if (response.statusCode == 200) {
            data.resultStatus = ResultStatus.success;
            data.resultData = response.data;
            // data.rootBean = NetResponseBean.fromJson(response.data);
          } else {
            _requestError(data);
          }
        } catch (e) {
          _requestError(data);
        }
    
        //拦截器处理
        NetWorkManger().responseInterceptor?.responseInterceptor(data);
        return data;
      }
    
      ///添加网络代理,用于抓包
      _addDioProxy(NetData data) {
        try {
          if (data.isSetProxy &&
              data.proxyPort.isNotEmpty &&
              data.proxyIp.isNotEmpty) {
            (dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate =
                (HttpClient client) {
              client.findProxy = (uri) {
                return "PROXY ${data.proxyIp}:${data.proxyPort}";
              };
              client.badCertificateCallback =
                  (X509Certificate cert, String host, int port) => true;
              return null;
            };
          }
        } catch (e) {
          print(e);
        }
      }
    
      @override
      cancelRequest({NetCancelToken? token}) {
        CancelToken _token = token ?? _cancelToken;
        _token.cancel();
      }
    
      _requestError(NetData data) {
        data.resultStatus = ResultStatus.serviceError;
        NetResponseBean root = NetResponseBean();
        root.success = "false";
        root.code = "-10001";
        root.msg = "网络异常,请稍后重试!";
        data.rootBean = root;
      }
    
      Future<bool> isConnected() async {
        var connectivityResult = await (Connectivity().checkConnectivity());
        if (connectivityResult == ConnectivityResult.mobile) {
          // I am connected to a mobile network.
          return true;
        } else if (connectivityResult == ConnectivityResult.wifi) {
          // I am connected to a wifi network.
          return true;
        }
        return false;
      }
    
      String getFileName(String filePath) {
        if (filePath.isEmpty || !filePath.contains("/")) {
          return "";
        }
        return filePath.substring(filePath.lastIndexOf("/") + 1, filePath.length);
      }
    }
    

    配置参数NetData

    class NetData {
      RequestType requestType = RequestType.POST; //请求类型
      Map<String, dynamic>? params; //参数
      Map<String, dynamic> header = NetWorkManger().header; //请求头
      String url = ""; //请求地址
      String baseUrl = "";
      NetCancelToken? cancelToken;
    
      ///上传,key是上传的key ,value是文件地址
      Map<String, String> uploadMap = {};
    
      ///下载储存文件的地址
      String downloadFilePath = '';
    
      int connectTimeOut = NetWorkManger().connectTimeOut; //连接超时时间:默认30秒
      int readTimeout = NetWorkManger().readTimeout; //读取超时时间:默认30秒
      String contentType = NetWorkManger().contentType; //http
      String proxyIp = NetWorkManger().proxyIp; //代理ip
      String proxyPort = NetWorkManger().proxyPort; //代理端口
      bool isSetProxy = NetWorkManger().isSetProxy; //是否开启代理
    
      //以下为返回数据
      ResultStatus? resultStatus; //请求状态
      dynamic resultData; //返回数据
      RequestType resultType = RequestType.POST; //解析
      NetBaseBean rootBean = NetResponseBean(); //解析bean 默认是rootBean 可以设置
    
      bool isEncryption = false; //参数,返回值是否加解密
      bool isShowLoading = false; //是否显示加载loading弹窗
    
      bool isSuccess() {
        return rootBean.isSuccess();
      }
    }
    

    网络框架的使用

    参数说明

    url 接口地址
    type 请求方式
    param 请求参数
    token 删除请求token,new NetCanceToken即可使用
    isEncryption 是否加密
    isShowLoading 是否显示加载弹窗
    success 成功,返回参数仅只是data数据,不包含code和msg
    error 失败,参数返回code和msg

    req(String url,  
       {RequestType type = RequestType.POST,  
       Map<String, dynamic>? param,  
       NetCancelToken? token,  
       bool isEncryption = false,  
       bool isShowLoading = true,  
       Function? success,  
       Function? error}) {}
    

    继承调用方式

    填空法
    用填空的方式设置请求参数
    继承BaseRequest<T>实现 T为返回data实体对象的类型
    initApiUrl() 设置->url
    addParam(String key, dynamic value) 设置->param
    addParams(Map<String, dynamic> map) 设置->params
    initReqType() 设置->get or post
    jsonToData() 设置-> 填jsonData解析成T类型的方法
    剩下参数 isEncryption isShowLoading等 需要更改可以在继承类中直接重写

    调用

         TestRequest req = TestRequest();
         req.addParam("key", "value");
         req.req((data){ 成功返回T->data }, (code, msg) {失败code msg });
    

    例子参考

    class LoginRequest extends BaseRequest<User> {
      @override
      String initApiUrl() {
        return "http://xxxxx";
      }
    
      @override
      RequestType initReqType() {
        return RequestType.GET;
      }
    
      @override
      User jsonToData(Map<String, dynamic> jsonData) {
        return User.fromJson(jsonData);
      }
    }
    
    

    post调用

    NetUtils().req("", 
         param: {},
         success: (success){},
         error: (code,msg){}); 
    

    get调用

    NetUtils().req("", 
         type = RequestType.GET,
         param: {},
         success: (success){},
         error: (code,msg){});    
    
    #### 数据返回获取更多的信息
    NetUtils().requestCommon("", 
         RequestType.GET,
         param: {}).then((value){  
         //TODO value是NetData,rootBean中包含接口返回的信息code,msg data  
    });
    

    上传

    参数说明

    url上传地址
    uploadMap 参数
    token 删除请求token,new NetCanceToken即可使用
    sendProgressCallback 上传进度
    isShowloading 是否显示加载弹框
    success 成功
    fail 失败

    调用

    NetUtils().requestUploadFile(String url,   
       Map<String,String> uploadMap,  
       {NetCancelToken? token,  
       Function(int, int)? sendProgressCallback,  
       bool isShowloading = true,  
       ValueChanged? success,  
       ValueChanged? fail}) {}  
    

    下载

    参数说明

    url上传地址
    filePath 储存路劲 ��
    param 参数
    token 删除请求token,new NetCanceToken即可使用
    progressCallback 下载进度
    isShowloading 是否显示加载弹框
    success 成功
    fail 失败

    调用

    requestDownLoading(String url,  
       String filePath,  
       {Map<String, dynamic>? param,  
       NetCancelToken? token,  
       Function(int, int)? progressCallback,  
       bool isShowloading = true,  
       ValueChanged? success,  
       ValueChanged? fail}) {}
    

    修改baseUrl调用 NetWorkManger().baseUrl

    url地址拼接上域名后,框架就不在拼接域名,可以用于多域名请求,解析的数据时,判断url是否包含当前域名

    根据url中域名的判断可进行多种解析

    相关文章

      网友评论

        本文标题:Flutter怎么搭建一套健壮可靠的网络框架

        本文链接:https://www.haomeiwen.com/subject/ndqjwrtx.html