学习Flutter的一个月了,说好了写博客,才写完一篇就断更了,很尴尬。
Dio
目前应该是Flutter最火的网络请求框架了,今天不分享网络请求实现,分享一下抓包。
抓包可以用Fiddler
或者Charles
,我当前的IP和Port为:192.168.0.85:8888
。
在手机的WIFI
->代理
->手动
配置主机名和端口号。
按照Dio文档配置如下:
import 'package:dio/dio.dart';
import 'package:dio/adapter.dart';
...
(dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate = (client) {
// config the http client
client.findProxy = (uri) {
//proxy all request to localhost:8888
return 'PROXY localhost:8888';
};
// you can also create a HttpClient to dio
// return HttpClient();
};
在实际抓包的时候发现,以上代码好像不生效,那是因为Flutter Dev Tools本身通过Socket
与手机连接,解决方法如下:
-
方法1. 将
localhost
改为具体的IP,例如192.168.0.85
,所以代码如下import 'package:dio/dio.dart'; import 'package:dio/adapter.dart'; ... (dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate = (client) { // config the http client client.findProxy = (uri) { //proxy all request to localhost:8888 return 'PROXY 192.168.0.85:8888'; }; // you can also create a HttpClient to dio // return HttpClient(); }; ``` 这种方式个人开发还行,如果是团队开发或者线下测试就不太友好了。
-
方法2. 配置设备监听的端口号,需要使用
adb reverse tcp:8888 tcp:8888
命令。这样配置有一个坏处就是
adb重启
就需要重新输入命令,对于没有安装adb
工具的还是不友好。 方法3. 结合方法1,动态配置代理。在
Dio
初始化之前,通过MethodChannel
调用Android\IOS
获取代理信息,动态配置Dio
。
flutter端代码如下:
Dio dio = Dio();
MethodChannel channel = const MethodChannel('com.muzi.http.proxy');
Future<String?> getHost = channel.invokeMethod('getProxyHost');
Future<String?> getPort = channel.invokeMethod('getProxyPort');
var result = await Future.wait([getHost, getPort]);
if (result.length == 2 &&
result[0] != null &&
result[0]!.isNotEmpty &&
result[1] != null &&
result[1]!.isNotEmpty) {
String host = result[0].toString();
String port = result[1].toString();
(dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate =
(HttpClient client) {
client.findProxy = (uri) {
return 'PROXY $host:$port';
};
};
}
android端代码如下:
class HttpProxyPlugin(messenger: BinaryMessenger): MethodChannel.MethodCallHandler {
private var channel: MethodChannel? = null
init {
channel = MethodChannel(messenger, "com.muzi.http.proxy")
channel?.setMethodCallHandler(this)
}
override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
when (call.method) {
"getProxyHost" -> result.success(getProxyHost())
"getProxyPort" -> result.success(getProxyPort())
}
}
private fun getProxyHost(): String? {
return System.getProperty("http.proxyHost")
}
private fun getProxyPort(): String? {
return System.getProperty("http.proxyPort")
}
}
IOS端不会,找个人会的同学干吧。。。
示例代码见GitHub