network
- aes 加解密操作
- entity 基礎(chǔ)實(shí)體類(lèi)
- interceptor 攔截器
- http_error 錯(cuò)誤碼
- net_exception 異常攔截
- vv_net_work 單例的Dio對(duì)象
Dio配合Charles 抓包配置,ConstantConfig.localProxy配置本機(jī)IP源哩,既可以實(shí)現(xiàn)抓包
if (ConstantConfig.localProxy.isNotEmpty) {
(_client.httpClientAdapter as DefaultHttpClientAdapter)
.onHttpClientCreate = (client) {
client.badCertificateCallback =
(X509Certificate cert, String host, int port) {
// if(cert.pem==PEM){ // Verify the certificate
// return true;
// }
return true;
};
client.findProxy = (uri) {
return ConstantConfig.localProxy;
};
};
}
網(wǎng)絡(luò)取消,結(jié)合ViewModel進(jìn)行取消,具體怎么取消的,記得看源碼
static Map<String, CancelToken> cancelTokens = new Map<String, CancelToken>();
///取消請(qǐng)求
static void cancelHttp(String tag) {
if (cancelTokens.containsKey(tag)) {
if (!cancelTokens[tag].isCancelled) {
cancelTokens[tag].cancel();
}
cancelTokens.remove(tag);
}
}
這里有一個(gè)比較重要的操作惜索,就是數(shù)據(jù)解析了。Dart語(yǔ)言沒(méi)有實(shí)際的泛型概念,無(wú)法類(lèi)似Android實(shí)體化泛型命贴,所以咧织,這里我們把數(shù)據(jù)塞進(jìn)BaseResponseEntity嗓袱,通過(guò)解析 var dynamicData = json.decode(decodeData);來(lái)達(dá)到業(yè)務(wù)獲取數(shù)據(jù)
if (baseResult['code'] == HTTP_SUCCEED) {
var data = baseResult['data'];
if (data != null) {
try {
//解密
String decodeData = EncryptUtil.aesDecode(data);
var dynamicData = json.decode(decodeData);
print('解密后的數(shù)據(jù)$decodeData');
BaseResponseEntity<T> baseResEntity = BaseResponseEntity(
data: dynamicData,
code: baseResult['code'],
msg: baseResult['msg'],
timeStamp: baseResult['timeStamp']);
return new Future.value(baseResEntity);
} catch (e) {
throw (new ResponseException(
code: baseResult['code'],
message: e.toString(),
errorData: baseResult['data']));
}
} else {
throw (new ResponseException(
code: baseResult['code'],
message: baseResult['msg'],
errorData: baseResult['data']));
}
}
通過(guò)上述net分析,以及網(wǎng)上大部分人的寫(xiě)法可以知道习绢。使用Dart的時(shí)候渠抹,解析數(shù)據(jù)有點(diǎn)小麻煩,F(xiàn)lutter-Habit通過(guò)JsonConvert.fromJsonAsT闪萄,擴(kuò)展了一個(gè)方法屬性梧却,來(lái)使業(yè)務(wù)更加簡(jiǎn)單
extension NetExtension<T> on Future<BaseResponseEntity<T>> {
Future<T> check() async {
var baseResponseEntity = await this;
return Future.value(JsonConvert.fromJsonAsT<T>(baseResponseEntity.data));
}
}
用法例子如下:
class LoginModel extends BaseModel {
Future<LoginRespEntity> login(LoginReqUserEntity loginReqUserEntity) =>
apiService
.request<LoginRespEntity>(
LoginApiService.loginUrl,
queryParameters: loginReqUserEntity.toJson(),
)
.check();
}
在具體的業(yè)務(wù)層使用
void toLogin(BuildContext context, String account, String password) {
var loginReqUserEntity = LoginReqUserEntity()
..loginName = "123"
..password = "456"
..organizeType = 3;
launch(() async {
var login = await model.login(loginReqUserEntity);
showToast(login.loginName);
NavigatorUtils.pushNamed(context, PassWordForgetPage.sName);
}, (err) {
});
}
注意,這里對(duì)launch的封裝,可以全局控制所有異常
void launch(Future<void> Function() future, HttpFailureCallback err,
{bool ignoreToast = false,
bool showLoadingIndicator = false,
bool isCancelable = true}) {
future().catchError((onError) {
///錯(cuò)誤所有的網(wǎng)絡(luò)異常
print("啥錯(cuò)誤${onError.toString()}");
err.call(Exception(
HttpError.checkNetError(onError, ignoreToast: ignoreToast)));
});
}
整體的業(yè)務(wù)結(jié)構(gòu)败去,比較核心的大概就是這兩個(gè)地方了放航。其他的看開(kāi)源的項(xiàng)目吧。
Flutter-Habit