创建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
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
网友评论