学习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