flutter之网络请求Dio

创建Dio单例类

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

class NetManager {
  static Dio _dio;
  static Dio getDio(String versionStr, String tokenStr) {
    if (_dio == null) {
      _dio = new Dio();
    }

//请求头
    Map 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 getVersion() async {
    try {
      PackageInfo packageInfo = await PackageInfo.fromPlatform();
      return packageInfo.version;
    } catch (e) {
      print("获取版本好错误=" + e.toString());
    }
  }

}

创建网络请求类HttpTools

//请求成功、请求失败的回调
typedef SuccCallback = Future Function(
    Map responseDic, Response response);
typedef FailCallback = Future Function(String errStr, DioError error);

/*区分网络请求类型get、post*/
enum HttpType {
  type_get,
  type_post,
}



/*图片上传类型区分类型*/
enum ImgFileType {
  type_data, //以二进制流形式上传List
  type_file, //以文件形式上传
}

/*存放正在loading的context们*/
final List contextList = List();

class HttpTools {
  /*put、post网络请求*/
  static void http(
      BuildContext context,
      HttpType type,
      String url,
      Map 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 data,
      File imgFile,
      Map 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 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) {
        //获取Map类型的返回数据,我们统一处理
        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) {
            //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类型的,我们不统一处理,但是也按照成功的情况处理
//        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 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 json) =>
      _$MessageItemModelFromJson(json);

  Map 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 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 _$MessageItemModelToJson(MessageItemModel instance) =>
    {
      '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]

你可能感兴趣的:(flutter之网络请求Dio)