问题:在flutter开发中,关于dio请求数据的时候导致整个应用的ui卡顿。
在反复调试发现:ui卡顿的只有https协议下ios手机!
尝试剥析问题
首先,我的代码是这样的:
页面
provider文件
api请求
,
dio配置
一开始以为是dio的问题,后来用了flutter的原生库http还以一样卡顿,就猜想可能是自己代码的问题(老夫疲惫😫)!
解决方法一:开个线程玩玩
在pubspec.yaml中引入包:
在我们的main的文件中添入 // 顶层isolate负载均衡,初始化时开辟两个isolate
final Future<LoadBalancer> loadBalancer = LoadBalancer.create(2, IsolateRunner.spawn);
创建文件Resolve
/// resolve方法接收参数:{
/// url、token、method、params
/// }
import 'dart:convert';
import 'dart:isolate';
import 'package:dio/dio.dart';
import 'package:isolate/load_balancer.dart';
import 'package:xth2_mobile/main.dart';
Dio api = Dio();
/// 解析工作类
class Resolve {
static Future<dynamic> resolve(Map data) async {
final ReceivePort receivePort = ReceivePort();
final LoadBalancer lb = await loadBalancer;
// 开启一个线程
await lb.run<dynamic, SendPort>(_parsingInIsolate, receivePort.sendPort);
final SendPort sendPort = await receivePort.first;
final ReceivePort resultPort = ReceivePort();
// 把传进来的参数发送给_ParseMessageProtocol
sendPort.send(_ParseMessageProtocol(data['token'], data['url'],
data['method'] ?? 'get', data['params'] ?? {}, resultPort.sendPort));
var res = await resultPort.first;
return res;
}
}
_parsingInIsolate(SendPort sendPort) {
final ReceivePort receivePort = ReceivePort();
sendPort.send(receivePort.sendPort);
receivePort.listen((message) async {
final String url = message.url;
final String token = message.token;
final String method = message.method;
final Map params = message.params;
try {
final res = await http(url, token, method, params);
Map sendData = parsedResult(res);
message.sendPort.send(sendData);
} catch (e) {
print('resolve报错:$e');
try {
Map sendData = errorResult(e);
message.sendPort.send(sendData);
} catch (e) {
print('resolve send error报错:$e');
}
}
});
}
// 独立封装dio,对传进的参数进行请求
http(String url, String token, String method, Map params) async {
api.options.contentType = 'application/json';
api.options.connectTimeout = 30 * 1000;
api.options.receiveTimeout = 30 * 1000;
api.options.headers = {
'x-access-token': token,
};
// 日志拦截器
api.interceptors.add(LogInterceptor(responseBody: true));
Response res;
if (method == 'get') {
res = await api.get(url);
} else if (method == 'post') {
if (params == {}) {
res = await api.post(url);
} else {
res = await api.post(url, data: params);
}
} else if (method == 'put') {
res = await api.put(url, data: params);
} else if (method == 'head') {
res = await api.head(url, data: params);
} else if (method == 'delete') {
res = await api.delete(url, data: params);
}
return res;
}
class _ParseMessageProtocol {
final String token;
final String url;
final String method;
final Map params;
final SendPort sendPort;
_ParseMessageProtocol(
this.token, this.url, this.method, this.params, this.sendPort);
}
Map parsedResult(res) {
dynamic result = json.decode(res.toString());
Map sendData = {
'code': result['code'],
'msg': result['msg'],
'data': result['data'],
};
return sendData;
}
Map errorResult(e) {
Map sendData = {
'code': 100000,
'msg': e.toString(),
'data': null,
};
return sendData;
}
然后我们就可以愉快的使用Isolate啦!😄
使用方法:
方法二: 终极解决方法
- 换证书
1. 使用 ssl_stapling_file 配置,从一个外部文件获取ocsp信息 ngx_ssl_stapling_file
2. 使用 ssl_stapling_responder配置,nginx会用这个设置覆盖证书里面的Authority Information Access信息,使得请求ocsp被发送到设置的服务器
这里推荐第二种,如果在多台机器上部署的话第一种比较麻烦
- github.com/dlecorfec/o… 可以参考如下配置:
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/ssl/ca-certs.pem;
ssl_stapling_responder http://YOUR_PROXY_IP:8080/;
- 如果是使用k8S + nginx-ingress 部署
首先将 nginx-ingress 更新到 0.31+ 这里有相关的变动日志。关于部署的冲突可以自行判断。
测试是否成功
openssl s_client -connect ${host}:443 -servername ${host} -status -tlsextdebug < /dev/null 2>&1 | grep -i "OCSP response"
将其中的 ${host} 改成自己的域名即可
OCSP response:
OCSP Response Data:
OCSP Response Status: successful (0x0)
Response Type: Basic OCSP Response
输出如上及说明已经解决了。
然后我们就可以继续愉快的玩耍Flutter啦!嘿嘿
生活不易,互相鼓励!!!
请看到这里的各位👍+关注!谢谢。