美文网首页
flutter之网络请求Dio

flutter之网络请求Dio

作者: xieyinghao | 来源:发表于2023-06-04 00:00 被阅读0次

    创建Dio单例类

    创建全局的dio单例类,不需要每次请求都创建Dio对象,节省系统开支
    创建NetManager类

    class NetManager {
      static Dio _dio;
      static Dio getDio(String versionStr, String tokenStr) {
        if (_dio == null) {
          _dio = new Dio();
        }
    
    //请求头
        Map<String, dynamic> headers = {
          "os": "ios",
          "Content-Type": "application/json;charset=UTF-8",
          "appname": "crm",
          "version": versionStr
        };
        if (tokenStr == null || tokenStr.length == 0) {
          headers.remove("x-token");
        } else {
          headers.putIfAbsent("x-token", () => tokenStr);
        }
    
    //设置请求头、超时时间等参数
        _dio.options = BaseOptions(
          headers: headers, //application/x-www-form-urlencoded
          contentType: ContentType.parse("application/json;charset=UTF-8"),
          connectTimeout: 15000,
          receiveTimeout: 15000,
        );
        print("token=="+tokenStr.toString());
        print("version=====" + versionStr);
    
        return _dio;
      }
    
    
      /*获取当前版本号*/
      static Future<String> getVersion() async {
        try {
          PackageInfo packageInfo = await PackageInfo.fromPlatform();
          return packageInfo.version;
        } catch (e) {
          print("获取版本好错误=" + e.toString());
        }
      }
    
    }
    

    创建网络请求类HttpTools

    //请求成功、请求失败的回调
    typedef SuccCallback = Future<void> Function(
        Map<String, dynamic> responseDic, Response response);
    typedef FailCallback = Future<void> Function(String errStr, DioError error);
    
    /*区分网络请求类型get、post*/
    enum HttpType {
      type_get,
      type_post,
    }
    
    
    
    /*图片上传类型区分类型*/
    enum ImgFileType {
      type_data, //以二进制流形式上传List<int>
      type_file, //以文件形式上传
    }
    
    /*存放正在loading的context们*/
    final List<BuildContext> contextList = List<BuildContext>();
    
    class HttpTools {
      /*put、post网络请求*/
      static void http(
          BuildContext context,
          HttpType type,
          String url,
          Map<String, dynamic> paraDic,
          SuccCallback succ,
          FailCallback fail) async {
        String urlStr = baseUrl + url; //完整地址,参数是拼接好之后传过来的,不需要再拼接了
    
        if (paraDic == null) {
          paraDic = Map();
        }
    
        try {
          Response response;
          NetManager.getVersion().then((versionStr) {
            //获取当前版本号。判断是否需要更新
            Utils.getToken().then((tokenStr) async {
              //获取当前cookie。判断是否登录
    
              Dio dio = NetManager.getDio(versionStr, tokenStr);
    
              //根据不同的网络请求修改参数
              if (
                  //url == xxx
              ) {
                //登录接口和评论接口都是使用formdata格式提交
                dio.options.contentType =
                    ContentType.parse("application/x-www-form-urlencoded");
              }
    
              HttpTools.showLoading(context, true); //显示loading
              if (type == HttpType.type_get) {
                response = await dio.get(urlStr).catchError((err) {
                  HttpTools.showLoading(context, false); //取消loading
                  fail(netWrongMsg, err);
                });
    
                dataProcessing(
                    context, dio, urlStr, response, paraDic, succ, fail); //数据处理
              } else if (type == HttpType.type_post) {
                response = await dio.post(urlStr, data: paraDic).catchError((err) {
                  HttpTools.showLoading(context, false); //取消loading
                  fail(netWrongMsg, err);
                });
                dataProcessing(
                    context, dio,urlStr, response, paraDic, succ, fail); //数据处理
              }
            });
          });
        } catch (e) {
          print("url=" + urlStr);
          print("paraDic=" + paraDic.toString());
          print("报错了" + e.toString());
          fail(e.toString(), DioError());
        }
      }
    
      /*文件上传*/
      static void upload(
          BuildContext context,
          String url,
          String name,
          String fileName,
          String primaryType,
          String subType,
          ImgFileType fileType,
          List<int> data,
          File imgFile,
          Map<String, dynamic> paraDic,
          SuccCallback succ,
          FailCallback fail) async {
        String urlStr = baseUrl + url; //完整地址,参数是拼接好之后传过来的,不需要再拼接了
    
        if (paraDic == null) {
          paraDic = Map();
        }
    
    
        if(fileType==ImgFileType.type_data){//以二进制流形式上传
          paraDic.putIfAbsent(
              name,
                  () => new UploadFileInfo.fromBytes(data, fileName,
                  contentType: ContentType(primaryType, subType))
          );
        }else if(fileType==ImgFileType.type_file){//以文件形式上传
          paraDic.putIfAbsent(name, ()=>UploadFileInfo(imgFile, fileName));
        }
    
    
    
    
        FormData formData = new FormData.from(paraDic);
        try {
          Response response;
          NetManager.getVersion().then((versionStr) {
            //获取当前版本号。判断是否需要更新
            Utils.getToken().then((tokenStr) async {
    
              Dio dio = NetManager.getDio(versionStr, tokenStr);
              
              
              dio.options.contentType = ContentType.parse("multipart/form-data");
    
              HttpTools.showLoading(context, true); //显示loading
              //获取当前cookie。判断是否登录
              response = await dio
                  .post(urlStr, data: formData)
                  .catchError((err) {
                HttpTools.showLoading(context, false);
                fail(netWrongMsg, err);
              });
              dataProcessing(context, dio, urlStr, response, paraDic, succ, fail); //数据处理
            });
          });
        } catch (e) {
          print("url=" + urlStr);
          print("paraDic=" + paraDic.toString());
          print("报错了" + e.toString());
          debugPrint('debugPrint');
          fail(e.toString(), DioError());
        }
      }
    
      /*get和post请求获取到的数据处理*/
      static dataProcessing(BuildContext context,Dio dio, String urlStr, Response response,
          Map<String, dynamic> paraDic, SuccCallback succ, FailCallback fail) {
        //尽量保证url和返回结果一块打印出来
        print("header===");
        print(dio.options.headers);
        print("url=" + urlStr);
        print("paraDic=" + paraDic.toString());
        print("response=" + response.toString());
    
        HttpTools.showLoading(context, false); //取消loading
    
    
    
    
    
    
        if (response != null && response.statusCode == 200 ) {
    
          //网络请求成功
          if (response.data.isNotEmpty && response.data is Map<String, dynamic>) {
            //获取Map<String,dynamic>类型的返回数据,我们统一处理
            String errcode = response.data["code"].toString();
            String message = response.data["message"].toString();
            var entity = response.data["data"];
    //        bool success = response.data["success"];
            bool success = errcode.isNotEmpty && errcode == "200" ? true : false;
    
            if (success == true) {
              //请求成功
              if (entity is Map<String, dynamic>) {
                //data是字典
                succ(entity, response);
              } else if (entity is List) {
                //data是数组
                succ({kUndefineKey: entity}, response);
              } else if (entity is String) {
                //data是字符串
                succ({kUndefineKey: entity}, response);
              } else if (entity is num) {
                //data是数值类型
                succ({kUndefineKey: entity}, response);
              } else {
                //未知情况按照成功处理
                succ({}, entity);
              }
            } else {
              if (errcode == "401") {
                //token超时
                Fluttertoast.showToast(msg: "登录超时,请重新登录");
                LoginModel.requestLogoutFun(context); //退出登录的接口,通知后台我退出登录了
                LoginModel.logoutSucc().then((_){//清除本地token
    //              RouteHelper.pushWidget(context,MyHomePage(0), replaceRoot: true);
                Navigator.of(context).pushAndRemoveUntil(new MaterialPageRoute(builder: (ctx){
                  return new LoginPage();
                }), (Route route)=>false);
                });
    
              }
    //          else if (errcode == "600") {
    //            print("版本更新");
    //          }
              else {
                //
                if (message.isEmpty || message.length == 0) {
                  fail(netWrongMsg, DioError());
                } else {
                  //未知状态吗按照错误情况处理
                  fail(message, DioError());
                }
              }
            }
          } else {
            //返回数据不是Map<String,dynamic>类型的,我们不统一处理,但是也按照成功的情况处理
    //        succ(Map(), response);
            fail(netWrongMsg, DioError());
          }
        } else {
          //此次网络请求不通
          fail(netWrongMsg, DioError());
        }
      }
    
      /*loading*/
      static void showLoading(BuildContext context, bool isShow) {
        if (isShow == true) {
          //a7c07
          bool isContain = false;
          contextList.forEach((c) {
            if (c.widget.toString() == context.widget.toString()) {
              isContain = true;
            }
          });
          if (!isContain) {
            print("显示loading");
            contextList.add(context);
    //        print("数组长度"+contextList.length.toString());
    //        contextList.forEach((c){
    //          print("数组元素=="+c.widget.toString());
    //        });
            showDialog(
                context: context,
                barrierDismissible: false,
                builder: (BuildContext c) {
                  return SpinKitFadingCircle(color: Colors.white);
                });
          }
        } else {
          List<BuildContext> removeList = new List();
    
          contextList.forEach((c) {
            if (context.widget.toString() == c.widget.toString()) {
              print("取消loading");
              removeList.add(c);
              if (Navigator.canPop(c)) {
                Navigator.pop(c);
              }
            }
          });
    
          removeList.forEach((rc) {
            contextList.remove(rc);
          });
        }
      }
    }
    

    关联实体类文件

    创建model
    import 'package:json_annotation/json_annotation.dart';

    part 'messageItemModel.g.dart';

    @JsonSerializable()
    class MessageItemModel{
    String id = "";//这条消息的id
    String toUserid = "";//这条消息是针对谁的用户id
    String from = ""; //这条消息是谁发起的用户id
    String infoDesc = "";//描述信息
    String createBy = "";//创建人
    String createDate = "";//创建时间
    String read = "";//是否已读 0未读

    String delFlag = "";

    MessageItemModel(this.id, this.toUserid, this.from, this.infoDesc,
    this.createBy, this.createDate, this.read, this.delFlag);

    factory MessageItemModel.fromJson(Map<String, dynamic> json) =>
    _$MessageItemModelFromJson(json);

    Map<String, dynamic> toJson() => _$MessageItemModelToJson(this);

    }

    使用
    
    HttpTools.http(context, HttpType.type_post, requestGetMyInfosAction, {"userId":userId,"PageNo":PageNo,"PageSize":PageSize}, (dic,response){
    
      if(dic!=null && dic["data"]!=null){
        MineMessageModel model = MineMessageModel.fromJson(dic["data"]);
        model.message = dic["message"];
        succ(model);
      }else{
        fail(netWrongMsg);
      }
    }, (errStr,error){
      fail(errStr);
    });
    
    此时下面代码报错,没关系,先这样写
    
    

    part 'messageItemModel.g.dart';

    
    在终端的项目根目录执行
    
    
    flutter packages pub run build_runner build
    

    此时生成了一个messageItemModel.g.dart文件,报错解决了,这个类里边的代码是自动生成的,不要手动修改,否则运行错误

    // GENERATED CODE - DO NOT MODIFY BY HAND
    
    part of 'messageItemModel.dart';
    
    // **************************************************************************
    // JsonSerializableGenerator
    // **************************************************************************
    
    MessageItemModel _$MessageItemModelFromJson(Map<String, dynamic> json) {
      return MessageItemModel(
          json['id'] as String,
          json['toUserid'] as String,
          json['from'] as String,
          json['infoDesc'] as String,
          json['createBy'] as String,
          json['createDate'] as String,
          json['read'] as String,
          json['delFlag'] as String);
    }
    
    Map<String, dynamic> _$MessageItemModelToJson(MessageItemModel instance) =>
        <String, dynamic>{
          'id': instance.id,
          'toUserid': instance.toUserid,
          'from': instance.from,
          'infoDesc': instance.infoDesc,
          'createBy': instance.createBy,
          'createDate': instance.createDate,
          'read': instance.read,
          'delFlag': instance.delFlag
        };
    

    用到了json_annotation和json_serializable
    (json_annotation)[https://pub.dev/packages/json_annotation]
    (json_serializable)[https://pub.dev/packages/json_serializable]

    作者:移动端_小刚哥
    链接:https://www.jianshu.com/p/776669e9797e
    来源:简书
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

    相关文章

      网友评论

          本文标题:flutter之网络请求Dio

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