Flutter+retrofit +dio+rxdart网络请求
2022-04-26 本文已影响0人
禄子_c79b
pubspec.yaml:
dependencies:
rxdart: ^0.23.1
retrofit: '>=3.0.0 <4.0.0'
logger: any #for logging purpose
dev_dependencies:
retrofit_generator: any
build_runner: '>1.3.0 <4.0.0'//用于生成.g文件
json_serializable: '>4.4.0'//生成实体
json_serializable代码在线生成网址
运行:flutter packages pub run build_runner build 会生成 .g文件
报错 flutter packages get
part 'RestClient.g.dart'; //必须配置,否则无法生成.g文件
BaseError
abstract class BaseError {
final int? code;
final String? message;
BaseError({this.code, this.message});
}
class NeedLogin implements BaseError {
@override
int get code => 401;
@override
String get message => "请先登录";
}
class NeedAuth implements BaseError {
@override
int get code => 403;
@override
String get message => "非法访问,请使用正确的token";
}
class UserNotExist implements BaseError {
@override
int get code => 408;
@override
String get message => "用户不存在";
}
class UserNameEmpty implements BaseError {
@override
int get code => 405;
@override
String get message => "用户名不能为空";
}
class PwdNotMatch implements BaseError {
@override
int get code => 409;
@override
String get message => "用户密码不正确";
}
class PwdEmpty implements BaseError {
@override
int get code => 406;
@override
String get message => "用户密码不能为空";
}
class OtherError implements BaseError {
final int? statusCode;
final String? statusMessage;
OtherError({this.statusCode, this.statusMessage});
@override
int? get code => statusCode;
@override
String? get message => statusMessage;
}
HeaderInterceptor
/// author : luzi
/// date : 2021/7/11
/// desc : 请求头拦截器
class HeaderInterceptor extends Interceptor {
@override
Future<void> onRequest(
RequestOptions options,
RequestInterceptorHandler handler,
) async {
Map<String, dynamic> headers = options.headers;
headers['clientId'] = 1; //渠道(1.APP 2.Web)
if (Platform.isAndroid) {
headers['systemName'] = 'Android'; //系统名称
} else if (Platform.isIOS) {
headers['systemName'] = 'iOS'; //系统名称
}
var time = DateTime.now().millisecondsSinceEpoch;
headers['ts'] = time; //时间戳
String sign = getParamsStr(options, time);
headers['sign'] = sign; //参数加密签名
headers['language'] = Get.locale?.countryCode ?? 'MY'; //语言环境
headers['Accept'] = 'application/json';
options.headers = headers;
handler.next(options);
}
getParamsStr(RequestOptions options, int time) {
StringBuffer stringBuffer = new StringBuffer();
String? paramsStr;
var method = options.method;
if (method == 'GET') {
if (options.queryParameters.isNotEmpty) {
String query = options.uri.query;
var splitArray = query.split('&');
var splayTreeMap = new SplayTreeMap();
splitArray.forEach((split) {
var splitChild = split.split('=');
splayTreeMap[splitChild[0]] = Uri.encodeQueryComponent(splitChild[1]);
});
paramsStr = json.encode(splayTreeMap);
if (paramsStr.isNotEmpty) {
stringBuffer.write('$paramsStr&');
} else {
stringBuffer.write('{}&');
}
} else {
stringBuffer.write('{}&');
}
} else if (method == 'POST') {
var data = options.data;
if (data is FormData) {
if (data.fields.isNotEmpty) {
String replace = data.fields
.join(",")
.replaceAll('MapEntry', '')
.replaceAll('(', '')
.replaceAll(')', '');
paramsStr = replace;
if (paramsStr.isNotEmpty) {
stringBuffer.write('{$paramsStr}&');
} else {
stringBuffer.write('{}&');
}
} else {
stringBuffer.write('{}&');
}
} else {
paramsStr = jsonEncode(data);
if (paramsStr.isNotEmpty) {
stringBuffer.write('$paramsStr&');
} else {
stringBuffer.write('{}&');
}
}
}
// NativeUtils.sendNativeData(NativeUtils.NATIVE_LOG, paramsStr.toString());
// print(paramsStr.toString());
stringBuffer.write('ts=$time&');
stringBuffer.write('tmpsign=${DioManager.getInstance().signKey}');
String toString = stringBuffer.toString().replaceAll("\"", "");
// NativeUtils.sendNativeData(NativeUtils.NATIVE_LOG, toString);
// print(toString);
// Get.log.printInfo(info: '拼接后:$toString');
var content = new Utf8Encoder().convert(toString);
var digest = md5.convert(content);
String md5Encode = hex.encode(digest.bytes).toUpperCase();
Get.log.printInfo(info: 'MD5:$md5Encode');
return md5Encode;
}
}
BaseDio
class BaseDio {
BaseDio._(); // 把构造方法私有化
static BaseDio? _instance;
static BaseDio? getInstance() { // 通过 getInstance 获取实例
_instance ??= BaseDio._();
return _instance;
}
Dio getDio() {
final Dio dio = Dio();
dio.options = BaseOptions(receiveTimeout: 55000, connectTimeout: 66000); // 设置超时时间等 ...
dio.interceptors.add(HeaderInterceptor()); // 添加拦截器,如 token之类,需要全局使用的参数
dio.interceptors.add(PrettyDioLogger( // 添加日志格式化工具类
requestHeader: true,
requestBody: true,
responseBody: true,
responseHeader: false,
compact: false,
));
return dio;
}
BaseError getDioError(Object obj) { // 这里封装了一个 BaseError 类,会根据后端返回的code返回不同的错误类
switch (obj.runtimeType) {
case DioError:
if ((obj as DioError).type == DioErrorType.response) {
final response = (obj as DioError).response;
if (response!.statusCode == 401) {
return NeedLogin();
} else if (response!.statusCode == 403) {
return NeedAuth();
} else if (response.statusCode == 408) {
return UserNotExist();
} else if (response.statusCode == 409) {
return PwdNotMatch();
} else if (response.statusCode == 405) {
return UserNameEmpty();
} else if (response.statusCode == 406) {
return PwdEmpty();
} else {
return OtherError(
statusCode: response.statusCode,
statusMessage: response.statusMessage,
);
}
}
}
return OtherError();
}
}
RestApi
part 'RestClient.g.dart'; //必须配置,否则无法生成.g文件
@RestApi(baseUrl: "https://uat.../")
abstract class RestClient {
factory RestClient({Dio? dio, String? baseUrl}) {
dio ??= BaseDio.getInstance()!.getDio();
return _RestClient(dio, baseUrl: baseUrl);
}
@POST("user/getImgCode.do")
// Future<Task> getTasks(@Body()Task task);
Future<Entity> getTasks(@Body() loginparms task);
}
//
// @JsonSerializable()
// class Task {
// String? imgToken;
// String? img;
//
// Task({this.imgToken, this.img});
//
// factory Task.fromJson(Map<String, dynamic> json) => _$TaskFromJson(json);
// Map<String, dynamic> toJson() => _$TaskToJson(this);
// }
@JsonSerializable()
class Entity extends Object {
@JsonKey(name: 'data')
Data data;
Entity(
this.data,
);
factory Entity.fromJson(Map<String, dynamic> srcJson) =>
_$EntityFromJson(srcJson);
Map<String, dynamic> toJson() => _$EntityToJson(this);
}
@JsonSerializable()
class Data extends Object {
@JsonKey(name: 'imgToken')
String imgToken;
@JsonKey(name: 'img')
String img;
Data(
this.imgToken,
this.img,
);
factory Data.fromJson(Map<String, dynamic> srcJson) =>
_$DataFromJson(srcJson);
Map<String, dynamic> toJson() => _$DataToJson(this);
}
@JsonSerializable()
class loginparms extends Object {
@JsonKey(name: 'parameter')
Parameter parameter;
@JsonKey(name: 'versionCode')
String versionCode;
loginparms(this.parameter,this.versionCode,);
factory loginparms.fromJson(Map<String, dynamic> srcJson) => _$loginparmsFromJson(srcJson);
Map<String, dynamic> toJson() => _$loginparmsToJson(this);
}
@JsonSerializable()
class Parameter extends Object {
Parameter();
factory Parameter.fromJson(Map<String, dynamic> srcJson) => _$ParameterFromJson(srcJson);
Map<String, dynamic> toJson() => _$ParameterToJson(this);
调用
Future<void> clickLike() async {
try {
print('你好============123456789--0}');
Parameter parameter=Parameter();
loginparms loginparm= loginparms(parameter,"");
Entity data = await RestClient().getTasks(loginparm); // 使用非常简单一句代码即可
// ImageCodeBean data = await RestClient().getTasks(map); // 使用非常简单一句代码即可
print('你好============123456789--5${data.data.imgToken}');
} catch (e) {
error: BaseDio.getInstance()!.getDioError(e);
//拿到BaseError对应自定义message错误信息
print('你好============123456789--1${BaseDio.getInstance()!.getDioError(e).message}');
}
}
可参照:https://www.psvmc.cn/article/2020-05-12-flutter-start-07-http-json.html