checkNetworkHealth method
检查网络健康状况 慢阈值: 1500ms 超时时间: 3000ms
返回值:
- available: 网络可用且速度正常
- slow: 网络可用但较慢
- unavailable: 网络不可用
使用示例:
final status = await NetworkUtil.checkNetworkHealth();
switch (status) {
case NetworkHealthStatus.available:
// 网络畅通
break;
case NetworkHealthStatus.slow:
// 网络慢,提示用户
break;
case NetworkHealthStatus.unavailable:
// 网络不可用,提示用户
break;
}
//或者
NetworkUtil.checkNetworkHealth().then((status) {
if (status == NetworkHealthStatus.unavailable) {
// 弹窗提示
}
});
//界面示例:
FutureBuilder<NetworkHealthStatus>(
future: NetworkUtil.checkNetworkHealth(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return CircularProgressIndicator();
}
switch (snapshot.data) {
case NetworkHealthStatus.available:
return Text('网络畅通');
case NetworkHealthStatus.slow:
return Text('网络较慢');
case NetworkHealthStatus.unavailable:
return Text('网络不可用');
default:
return Text('未知状态');
}
},
)
Implementation
Future<NetworkStatus> checkNetworkHealth({
int slowThresholdMs = 3000,
int timeoutMs = 10000,
}) async {
final completer = Completer<NetworkStatus>();
bool hasSuccess = false;
// 记录每个节点的响应时间
final Map<String, int> responseTimes = {};
final urls = _testUrls + extraUrls;
// 为每个URL创建单独的CancelToken
final cancelTokens = urls.map((_) => CancelToken()).toList();
for (var i = 0; i < urls.length; i++) {
final url = urls[i];
final cancelToken = cancelTokens[i];
Logger.log('网络健康检测: 开始请求 $url');
final stopwatch = Stopwatch()..start();
Dio()
.get(
url,
options: Options(
receiveTimeout: Duration(milliseconds: timeoutMs),
sendTimeout: Duration(milliseconds: timeoutMs),
),
cancelToken: cancelToken,
)
.then((response) {
stopwatch.stop();
final responseTime = stopwatch.elapsedMilliseconds;
responseTimes[url] = responseTime;
Logger.log(
'网络健康检测: $url 响应 statusCode=${response.statusCode}, 耗时=${responseTime}ms');
if (response.statusCode == 200) {
hasSuccess = true;
}
}).catchError((e) {
stopwatch.stop();
final responseTime = stopwatch.elapsedMilliseconds;
responseTimes[url] = responseTime;
Logger.log('网络健康检测: $url 请求失败/超时,耗时=${responseTime}ms,错误: $e');
});
}
// 超时后判断最终状态
Future.delayed(Duration(milliseconds: timeoutMs + 500), () {
// 取消所有未完成的请求
for (var token in cancelTokens) {
if (!token.isCancelled) {
token.cancel('检测超时,取消剩余请求');
}
}
// 打印所有节点的响应时间
Logger.log('网络健康检测: 所有节点响应时间统计 >>>');
responseTimes.forEach((url, time) {
Logger.log('节点: $url, 耗时: ${time}ms');
});
Logger.log('网络健康检测: 统计结束 <<<');
if (!completer.isCompleted) {
if (hasSuccess) {
// 获取最快的响应时间
final fastestTime = responseTimes.values.reduce(min);
fastResponseTime = fastestTime;
if (fastestTime <= slowThresholdMs) {
Logger.log('网络健康检测: 最快节点响应时间 ${fastestTime}ms,判定为 available');
completer.complete(NetworkStatus.available);
} else {
Logger.log('网络健康检测: 最快节点响应时间 ${fastestTime}ms,判定为 slow');
completer.complete(NetworkStatus.slow);
}
} else {
Logger.log('网络健康检测: 所有节点都失败,判定为 unavailable');
completer.complete(NetworkStatus.unavailable);
}
}
});
return completer.future;
}