diff --git a/example/lib/main.dart b/example/lib/main.dart index e594288..f594c99 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -1,8 +1,8 @@ import 'package:flutter/material.dart'; import 'package:zhiying_comm/zhiying_comm.dart'; -import 'package:zhiying_comm_example/device_info_page.dart'; -import 'package:zhiying_comm_example/log_util.dart'; -import 'package:zhiying_comm_example/package_info_page.dart'; +// import 'package:zhiying_comm_example/device_info_page.dart'; +// import 'package:zhiying_comm_example/log_util.dart'; +// import 'package:zhiying_comm_example/package_info_page.dart'; void main() => runApp(MyApp()); @@ -32,11 +32,11 @@ class _MyAppState extends State { class HomePage extends StatelessWidget { netPost() async { - dynamic result = await NetUtil.post('/api/v1/rec/featured?page=1', params: null); + dynamic result = + await NetUtil.post('/api/v1/rec/featured?page=1', params: null); print("result === ${result?.toString()}"); } - @override Widget build(BuildContext context) { return SingleChildScrollView( @@ -48,7 +48,7 @@ class HomePage extends StatelessWidget { RaisedButton( onPressed: () { Navigator.push(context, MaterialPageRoute(builder: (_) { - return DeviceInfoPage(); + // return DeviceInfoPage(); })); }, child: Text('设备信息'), @@ -56,7 +56,7 @@ class HomePage extends StatelessWidget { RaisedButton( onPressed: () { Navigator.push(context, MaterialPageRoute(builder: (_) { - return PackageInfoPage(); + // return PackageInfoPage(); })); }, child: Text('应用信息'), @@ -89,26 +89,22 @@ class HomePage extends StatelessWidget { }, child: Text('网络同步请求(无缓存)'), ), - RaisedButton( - onPressed: (){ - LogUtil.test(); + onPressed: () { + // LogUtil.test(); }, child: Text('显示日志'), ), RaisedButton( - onPressed: (){ - Navigator.push(context, MaterialPageRoute( - builder: (_){ - return Logger(); - } - )); + onPressed: () { + Navigator.push(context, MaterialPageRoute(builder: (_) { + return Logger(); + })); }, child: Text('打开日志视图'), ), - RaisedButton( - onPressed: (){ + onPressed: () { // NetUtil.request('/api/v1/mod', params: {'ids': [6] } ,method: NetMethod.POST, // onSuccess: (params){ // Logger.log("onSuccess#$params"); @@ -118,23 +114,43 @@ class HomePage extends StatelessWidget { // }); testPost(); - }, child: Text('测试接口'), ), + RaisedButton( + onPressed: () async { + Api api = Api('/api/v1/user/info', method: NetMethod.GET); - + // api.onCache().then((cache) { + // print('读取缓存 ${cache.toString()}'); + // return api.onRequest(); + // }).then((result) { + // print('网络请求 ${result.toString().length}'); + // }).catchError((error) { + // print('aaaa'); + // print('error: ${error.toString()}'); + // }); + var cache = await api.onCache(); + var result = await api.onRequest(); + }, + child: Text('新网络请求'), + ), ], ), ), ); } - void testPost() async{ - var cached = await NetUtil.getRequestCachedData( '/api/v1/mod', params: {'ids': [7] }); + void testPost() async { + var cached = await NetUtil.getRequestCachedData('/api/v1/mod', params: { + 'ids': [7] + }); print("cahced ${cached?.toString()}"); - var param = await NetUtil.post('/api/v1/mod', params: {'ids': [7] }, method: NetMethod.POST); + var param = await NetUtil.post('/api/v1/mod', + params: { + 'ids': [7] + }, + method: NetMethod.POST); print('apapapsdjfdsjf: ${param?.toString()}'); } - } diff --git a/lib/util/api.dart b/lib/util/api.dart new file mode 100644 index 0000000..8f13fdc --- /dev/null +++ b/lib/util/api.dart @@ -0,0 +1,250 @@ +import 'package:dio/dio.dart'; +import 'package:dio/adapter.dart'; +import 'package:zhiying_comm/util/empty_util.dart'; +import 'dart:io'; +import 'dart:convert'; +import 'package:zhiying_comm/zhiying_comm.dart'; + +import 'global_config.dart'; +import 'shared_prefe_util.dart'; + +class Api { + final String path; + Map params; + final NetMethod method; + + static Dio _dio; + static get _net async { + if (_dio == null) { + var setting = await NativeUtil.getSetting(); + String domain = setting['domain']; //'http://www.hairuyi.com/'; + _config(domain, proxyUrl: '192.168.0.112:8888'); + } + return _dio; + } + + Api(this.path, {this.params, this.method = NetMethod.POST}) { + this.params = params ?? {}; + } + + Future onCache() async { + String cacheKey = getRequestParamsCachedKey(params, path); + // 读取缓存 + Map cacheMap = + await SharedPreferencesUtil.getNetCacheResult(cacheKey); + + if (!EmptyUtil.isEmpty(cacheMap) && + cacheMap.containsKey(GlobalConfig.HTTP_RESPONSE_KEY_CODE) && + (cacheMap[GlobalConfig.HTTP_RESPONSE_KEY_CODE] == + GlobalConfig.RESPONSE_SUCCESS_CODE || + cacheMap[GlobalConfig.HTTP_RESPONSE_KEY_CODE] == + '${GlobalConfig.RESPONSE_SUCCESS_CODE}') && + !EmptyUtil.isEmpty(cacheMap[GlobalConfig.HTTP_RESPONSE_KEY_DATA])) { + return cacheMap[GlobalConfig.HTTP_RESPONSE_KEY_DATA]; + } + return {}; + } + + Future onRequest() async { + Map result = {}; + + try { + Dio net = await _net; + Map headers = await _getHeaders(); + var responds = await net.request(path, + data: params, + options: Options(method: enumToString(method), headers: headers)); + + result = responds.data is Map ? responds.data : jsonDecode(responds.data); + + String cacheKey = getRequestParamsCachedKey(params, path); + _setCallBackCacheData(cacheKey, + responds.data is Map ? jsonEncode(responds.data) : responds.data); + } on DioError catch (e) { + _formatError(e); + } + + return result; + } + + // 获取headers,headers保存各种签名认证信息 + Future> _getHeaders() async { + Map headers = Map(); + headers['device'] = 'wx_applet'; + headers['Platform'] = 'wx_applet'; + + // token 读取SP缓存中的用户token + String token = await SharedPreferencesUtil.getStringValue( + GlobalConfig.SHARED_KEY_TOKEN) ?? + ''; + const bool inProduction = const bool.fromEnvironment("dart.vm.product"); + if (!inProduction && token != '') { + token = '7f7bdb785dcb02a4536bea2ffe299eda352e127f'; + } + + if (token != null && token != '') { + headers['token'] = token; + } + return headers; + } + + /// 配置网络请求,基础地址,代理地址,如:192.168.0.123:8888(代理地址生产环境无效) + /// apiVersion 接口版本 + static void _config(String baseUrl, {String proxyUrl}) { + _dio = Dio(BaseOptions( + method: "post", + baseUrl: baseUrl, + connectTimeout: 15000, + receiveTimeout: 15000, + contentType: Headers.jsonContentType, + followRedirects: true, + )); + _dio.interceptors.add(_NetInterceptors()); +// _dio.interceptors.add(LogInterceptor()); + + const bool inProduction = const bool.fromEnvironment("dart.vm.product"); + if (proxyUrl != null && proxyUrl != '' && !inProduction) { + _setProxy(proxyUrl); + } + } + + /// 设置代理 + static void _setProxy(String proxyUrl) { + (_dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate = + (HttpClient client) { + client.findProxy = (uri) { + return "PROXY $proxyUrl"; + }; + client.badCertificateCallback = + (X509Certificate cert, String host, int port) => true; + }; + } + + /// 获取请求缓存成功的数据 + static Future _onCallBackCacheData( + OnCache onCache, String cacheKey) async { + // 读取缓存 + Map cacheMap = + await SharedPreferencesUtil.getNetCacheResult(cacheKey); + + if (!EmptyUtil.isEmpty(cacheMap) && + cacheMap.containsKey(GlobalConfig.HTTP_RESPONSE_KEY_CODE) && + (cacheMap[GlobalConfig.HTTP_RESPONSE_KEY_CODE] == + GlobalConfig.RESPONSE_SUCCESS_CODE || + cacheMap[GlobalConfig.HTTP_RESPONSE_KEY_CODE] == + '${GlobalConfig.RESPONSE_SUCCESS_CODE}') && + !EmptyUtil.isEmpty(cacheMap[GlobalConfig.HTTP_RESPONSE_KEY_DATA])) { + onCache(cacheMap[GlobalConfig.HTTP_RESPONSE_KEY_DATA]); + return; + } + return; + } + + /// 缓存请求成功的数据 + static void _setCallBackCacheData(String cacheKey, String value) async { + SharedPreferencesUtil.setNetCacheResult(cacheKey, value); + } + + /// 根据请求参数,获取缓存的数据 + static Future getRequestCachedData(String url, + {Map params}) async { + Map cacheMap = + await SharedPreferencesUtil.getNetCacheResult( + getRequestParamsCachedKey(params, url)); + if (!EmptyUtil.isEmpty(cacheMap) && + cacheMap.containsKey(GlobalConfig.HTTP_RESPONSE_KEY_CODE) && + (cacheMap[GlobalConfig.HTTP_RESPONSE_KEY_CODE] == + GlobalConfig.RESPONSE_SUCCESS_CODE || + cacheMap[GlobalConfig.HTTP_RESPONSE_KEY_CODE] == + '${GlobalConfig.RESPONSE_SUCCESS_CODE}') && + !EmptyUtil.isEmpty(cacheMap[GlobalConfig.HTTP_RESPONSE_KEY_DATA])) { + return cacheMap[GlobalConfig.HTTP_RESPONSE_KEY_DATA]; + } + return null; + } + + /// 判断后台返回是否成功 + static bool isSuccess(Map data) { + try { + if (!EmptyUtil.isEmpty(data) && + (data[GlobalConfig.HTTP_RESPONSE_KEY_CODE] == + GlobalConfig.RESPONSE_SUCCESS_CODE || + data[GlobalConfig.HTTP_RESPONSE_KEY_CODE] == + '${GlobalConfig.RESPONSE_SUCCESS_CODE}')) { + return true; + } + } catch (e) { + return false; + } + return false; + } + + /// 根据请求参数,获取缓存的Key + static String getRequestParamsCachedKey( + Map map, String path) { + if (EmptyUtil.isEmpty(map)) { + return EncodeUtil.generateMd5(path); + } + return EncodeUtil.generateMd5(path + map.toString()); + } + + /// 签名 + static String signWithArray(List params) { + // 字母升序 + params.sort(); + String result = ""; +// result += secret_key; + params.forEach((param) { + result += param; + }); +// result += secret_key; + return EncodeUtil.generateMd5(result); + } + + /* + * error统一处理 + */ + static void _formatError(DioError e) { + if (e.type == DioErrorType.CONNECT_TIMEOUT) { + Logger.error('连接超时: ${e.toString()}'); + } else if (e.type == DioErrorType.SEND_TIMEOUT) { + Logger.error('请求超时: ${e.toString()}'); + } else if (e.type == DioErrorType.RECEIVE_TIMEOUT) { + Logger.error('响应超时: ${e.toString()}'); + } else if (e.type == DioErrorType.RESPONSE) { + Logger.error('出现异常: ${e.toString()}'); + } else if (e.type == DioErrorType.CANCEL) { + Logger.error('请求取消: ${e.toString()}'); + } else { + Logger.error('未知错误: ${e.toString()}'); + } + } +} + +/** + * @description: 网络请求拦截器 + * @param {type} + * @return: + */ +class _NetInterceptors extends InterceptorsWrapper { + @override + Future onRequest(RequestOptions options) { + Logger.net(options?.uri?.toString(), data: options.data.toString()); + // TODO 加密? + return super.onRequest(options); + } + + @override + Future onResponse(Response response) { + Logger.endNet(response?.request?.uri?.toString(), + data: response?.data?.toString() ?? ''); + // TODO 解密? + return super.onResponse(response); + } + + @override + Future onError(DioError err) { +// Logger.error(err); + return super.onError(err); + } +} diff --git a/lib/util/router_util.dart b/lib/util/router_util.dart index 705ec7d..4686504 100644 --- a/lib/util/router_util.dart +++ b/lib/util/router_util.dart @@ -19,21 +19,31 @@ class RouterUtil { print('skipIdentifier: ${skipIdentifier}'); if (requiredLogin == '1') { - UserInfoModel user = await Provider.of(context, listen: false).getUserInfoModel(); + UserInfoModel user = + await Provider.of(context, listen: false) + .getUserInfoModel(); print(user.toString()); if (user?.token == null || user.token == '') { print('need login...'); - return Navigator.of(context).push(MaterialPageRoute(builder: (BuildContext context) { + return Navigator.of(context) + .push(MaterialPageRoute(builder: (BuildContext context) { return LoginPage(model); })); } } - return Navigator.of(context).push(MaterialPageRoute(builder: (BuildContext context) { - if (PageFactory.hasRegisted(skipIdentifier)) { - return PageFactory.create(skipIdentifier, model); - } - return EmptyPage(); + Widget page = EmptyPage(); + if (PageFactory.hasRegisted(skipIdentifier)) { + page = PageFactory.create(skipIdentifier, model); + } else { + Api api = Api('/api/v1/mod/${skipIdentifier.toString()}', + method: NetMethod.GET); + var result = await api.onRequest(); + page = PageFactory.create('index', Map.from(result)); + } + return Navigator.of(context) + .push(MaterialPageRoute(builder: (BuildContext context) { + return page; })); } } diff --git a/lib/zhiying_comm.dart b/lib/zhiying_comm.dart index 190df4c..2e2af93 100644 --- a/lib/zhiying_comm.dart +++ b/lib/zhiying_comm.dart @@ -17,6 +17,7 @@ export 'util/router_util.dart'; export 'util/log/let_log.dart'; export 'util/empty_util.dart'; export 'util/global_config.dart'; +export 'util/api.dart'; // 用户信息 export 'models/user/user_info_model.dart';