dio: ^3.0.6
uni_links: ^0.4.0
1,dio的使用,并且二次封装,还设置了抓包代理
import 'dart:async';
import 'dart:io';
import 'package:dio/adapter.dart';
import 'package:dio/dio.dart';
/*
* 封装 dio 请求
*
*/
class DioUtils {
/// global dio object
static Dio dio;
/// default options
static const String API_PREFIX = 'https://api.apiopen.top/'; //'https://novel.dkvirus.com/api/v1';
static const int CONNECT_TIMEOUT = 10000;
static const int RECEIVE_TIMEOUT = 3000;
static const String LOACLHOST = '192.168.1.74';
/// http request methods
static const String GET = 'get';
static const String POST = 'post';
static const String PUT = 'put';
static const String PATCH = 'patch';
static const String DELETE = 'delete';
///Get请求测试
static void getHttpTest() async {
try {
Response response = await Dio().get("http://www.baidu.com");
print("response$response");
} catch (e) {
print(e);
}
}
///Post请求测试
static void postHttp<T>(
String url, {
parameters,
Function(T t) onSuccess,
Function(String error) onError,
}) async {
///定义请求参数
parameters = parameters ?? {};
//参数处理
parameters.forEach((key, value) {
if (url.indexOf(key) != -1) {
url = url.replaceAll(':$key', value.toString());
}
});
try {
Response response;
Dio dio = createInstance();
response = await dio.post(url, data: parameters);
if (response.statusCode == 200) {
if (onSuccess != null) {
onSuccess(response.data);
}
} else {
throw Exception('statusCode:${response.statusCode}');
}
print('响应数据:' + response.toString());
} catch (e) {
print('请求出错:' + e.toString());
onError(e.toString());
}
}
///Get请求测试
static void dioHttp<T>(
String url,
Map<String, String> headers,
String method, {
params,
Function(T t) onSuccess,
Function(String error) onError,
}) async {
///定义请求参数
params = params ?? {};
//参数处理
params.forEach((key, value) {
if (url.indexOf(key) != -1) {
url = url.replaceAll(':$key', value.toString());
}
});
try {
Response response;
Dio dio = createInstance();
//配置HTTP代理
// proxyDio();
if (headers != null) {
///显示指定Map的限定类型 动态添加headers
dio.options.headers.addAll(new Map<String, String>.from(headers));
}
if (method == 'get') {
if (params != null && params.isNotEmpty) {
response = await dio.get(url, queryParameters: params);
} else {
response = await dio.get(url);
}
} else if (method == 'post') {
if (params != null && params.isNotEmpty) {
response = await dio.post(url, data: params);
} else {
response = await dio.post(url);
}
}
if (response.statusCode == 200) {
if (onSuccess != null) {
onSuccess(response.data);
}
} else {
throw Exception('statusCode:${response.statusCode}');
}
print('响应数据:' + response.toString());
} catch (e) {
print('请求出错:' + e.toString());
onError(e.toString());
}
// response = await dio.get("/test?id=12&name=wendu");
// print(response.data.toString());
// Optionally the request above could also be done as
// response = await dio.get("/test", queryParameters: {"id": 12, "name": "wendu"});
// print(response.data.toString());
}
/// request method
//url 请求链接
//parameters 请求参数
//metthod 请求方式
//onSuccess 成功回调
//onError 失败回调
static Future<Map> request<T>(String url,
{parameters, method, Function(T t) onSuccess, Function(String error) onError}) async {
parameters = parameters ?? {};
method = method ?? 'GET';
/// 请求处理
parameters.forEach((key, value) {
if (url.indexOf(key) != -1) {
url = url.replaceAll(':$key', value.toString());
}
});
/// 打印:请求地址-请求方式-请求参数
print('请求地址:【' + method + ' ' + url + '】');
print('请求参数:' + parameters.toString());
Dio dio = createInstance();
//请求结果
var result;
try {
Response response = await dio.request(url, data: parameters, options: new Options(method: method));
result = response.data;
if (response.statusCode == 200) {
if (onSuccess != null) {
onSuccess(result);
}
} else {
throw Exception('statusCode:${response.statusCode}');
}
print('响应数据:' + response.toString());
} on DioError catch (e) {
print('请求出错:' + e.toString());
onError(e.toString());
}
return result;
}
/// 创建 dio 实例对象
static Dio createInstance() {
if (dio == null) {
/// 全局属性:请求前缀、连接超时时间、响应超时时间
var options = BaseOptions(
connectTimeout: 15000,
receiveTimeout: 15000,
responseType: ResponseType.plain,
validateStatus: (status) {
// 不使用http状态码判断状态,使用AdapterInterceptor来处理(适用于标准REST风格)
return true;
},
baseUrl: "https://api.apiopen.top/",
);
dio = new Dio(options);
}
return dio;
}
/// 清空 dio 对象
static clear() {
dio = null;
}
static void proxyDio() {
(dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate = (client) {
client.findProxy = (url) {
return "PROXY $LOACLHOST:8888";
};
//抓Https包设置
client.badCertificateCallback = (X509Certificate cert, String host, int port) => true;
};
}
}
使用的时候的代码:
//get获取
void getDioList(String string, String method, String sid) {
///显示指定Map的限定类型 ?page=1&count=2&type=video
//在super.initState(); 写
// FormData formData = new FormData.from({
// "uuid": "9dad1c81889ff0ea8c8c5ade6a5e36e3",
// "sign": "",
// "sso_id": "",
// "own_version": "100",
// "channel": "ios",
// "dev_os_version": "iOS12.3.1",
// "timestamp": "1564974676",
// "screen_size": "[375,667]",
// "is_jailbreak": 0,
// "os": "ios",
// "device_name": "iPhone6S",
// "os_version": "",
// "country_code": "CN",
// "ios_version": "1.0.0",
// });
Map<String, String> parms = {'name': '$sid'}; //{"page": "1", "count": "2", "type": "video"};
Map<String, String> headers = {};
DioUtils.dioHttp(
string,
headers,
method,
params: parms,
onSuccess: (data) {
print("成功:" + data.toString());
//反序列化
Map<String, dynamic> jsonMsg = json.decode(data.toString());
Autogenerated autogenerated = Autogenerated.fromJson(jsonMsg);
//序列化
String date = json.encode(autogenerated);
//更新ui
setState(() {
respons = autogenerated.result.toString();
});
},
onError: (error) {
print("成功:" + error.toString());
setState(() {
respons = error.toString();
});
},
);
}
顺便拿到的数据还序列化了,https://javiercbk.github.io/json_to_dart/ 这个网站也可以反序列化实例
2,niu_links学习:
先配置Android
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<!-- Accepts URIs that begin with YOUR_SCHEME://YOUR_HOST -->
<data
android:scheme="unilinks"
android:host="example.com" />
</intent-filter>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<!-- Accepts URIs that begin with https://YOUR_HOST -->
<data
android:scheme="https"
android:host="example.com" />
</intent-filter>
ios的配置:info.plist
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLName</key>
<string>com.example.uniLinksExample</string>
<key>CFBundleURLSchemes</key>
<array>
<string>unilinks</string>
</array>
</dict>
</array>
配置Runner,新建文件,
main.dart文件:
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutterweixin/ui/pages/mine/test_page.dart';
import 'package:provider/provider.dart';
import 'package:uni_links/uni_links.dart';
import 'ui/bloc/counter_bloc.dart';
import 'ui/pages/main_page.dart';
import 'utils/changenotifier.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => new _MyAppState();
}
class _MyAppState extends State<MyApp> with WidgetsBindingObserver {
int index = 0;
StreamSubscription _sub;
String _latestLink = 'Unknown';
Uri _latestUri;
var mynavigatorkey = GlobalKey<NavigatorState>();
// This widget is the root of your application.
@override
void initState() {
// TODO: implement initState
super.initState();
initPlatformState();
}
@override
void dispose() {
if (_sub != null) _sub.cancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
Widget homeWidget = Mainpage();
return MultiProvider(
providers: [ChangeNotifierProvider.value(value: MyChangeNotifier())],
child: MaterialApp(
//提出key:navigatorstate
navigatorKey: mynavigatorkey,
title: 'Flutter Demo',
debugShowCheckedModeBanner: false,
//去标签
theme: ThemeData.light().copyWith(
platform: TargetPlatform.iOS,
// canvasColor: Colors.amber,
primaryColor: Colors.blue,
accentColor: Colors.green,
indicatorColor: Colors.pink,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: homeWidget,
//动态组件
onGenerateRoute: onGenerateRoute,
// initialRoute: '/',
// routes: {
// '/':(context) => SplashPage(),
// '/home':(context) => Mainint(),
// },
),
);
}
Future<void> initPlatformState() async {
_sub = getLinksStream().listen((String link) {
if (!mounted) return;
setState(() {
_latestLink = link ?? "Unknown";
_latestUri = null;
try {
if (link != null) _latestUri = Uri.parse(link);
} on FormatException {}
});
}, onError: (err) {
if (!mounted) return;
setState(() {
_latestLink = 'Failed to get latest link: $err.';
_latestUri = null;
});
});
getLinksStream().listen((String link) {
print('got link: $link');
}, onError: (err) {
print('got err: $err');
});
String initialLink;
Uri initialUri;
try {
initialLink = await getInitialLink();
print('initial link: $initialLink');
if (initialLink != null) initialUri = Uri.parse(initialLink);
} on PlatformException {
initialLink = 'Failed to get initial link.';
initialUri = null;
} on FormatException {
initialLink = 'Failed to parse the initial link as Uri.';
initialUri = null;
}
if (!mounted) return;
// setState(() {
// _latestLink = initialLink;
// _latestUri = initialUri;
// });
_latestLink = initialLink;
_latestUri = initialUri;
final queryParams = _latestUri?.queryParametersAll?.entries?.toList();
String pageType;
String taskID;
if (queryParams != null) {
for (var param in queryParams) {
if (param.key == 'page') {
pageType = param.value.length > 0 ? param.value[0] : null;
}
if (param.key == 'taskid') {
taskID = param.value.length > 0 ? param.value[0] : null;
}
}
}
print(pageType);
if (pageType == 'report') {
mynavigatorkey.currentState.pushNamed("/testdio");
}
}
}
final routes = {"/main": (context) => Mainpage(), "/testdio": (context) => TestBlocDioPage()};
Function onGenerateRoute = (RouteSettings settings) {
final String name = settings.name;
final Function buildContext = routes[name];
Route route;
if (buildContext != null) {
if (settings.arguments != null) {
route = MaterialPageRoute(builder: (context) => buildContext(context, arguments: settings.arguments));
} else {
route = MaterialPageRoute(builder: (context) => buildContext(context));
}
}
return route;
};
中转html文件代码,记得把自己的hosts和scheme配置上。
<html xmlns=http://www.w3.org/1999/xhtml>
<head>
<meta http-equiv=Content-Type content="text/html;charset=utf-8">
<title>Your Title</title>
</head>
<body>
<style>
#mobliestart{font-size:40px;}
</style>
<a href='yourScheme://yourHost?page=report&taskid=1' id="mobliestart">点击打开APP</a>
<script type="text/javascript">
function applink(){
window.location = 'yourScheme://yourHost?page=report&taskid=1';
}
applink();
</script>
</body>
</html>
建议dio和niu_links配合官方文档和我的代码看,就是一整套,官方文档给的只是小例子,不够用。