diff --git a/lib/http/init.dart b/lib/http/init.dart index 9537e2ca9..9b845c7fc 100644 --- a/lib/http/init.dart +++ b/lib/http/init.dart @@ -16,6 +16,7 @@ import 'package:PiliPlus/utils/storage_pref.dart'; import 'package:PiliPlus/utils/utils.dart'; import 'package:archive/archive.dart'; import 'package:brotli/brotli.dart'; +import 'package:connectivity_plus/connectivity_plus.dart'; import 'package:dio/dio.dart'; import 'package:dio/io.dart'; import 'package:dio_http2_adapter/dio_http2_adapter.dart'; @@ -115,28 +116,18 @@ class Request { return h11; } - /* - * config it and create - */ - Request._internal() { - //BaseOptions、Options、RequestOptions 都可以配置参数,优先级别依次递增,且可以根据优先级别覆盖参数 - BaseOptions options = BaseOptions( - //请求基地址,可以包含子路径 - baseUrl: HttpString.apiBaseUrl, - //连接服务器超时时间,单位是毫秒. - connectTimeout: const Duration(milliseconds: 10000), - //响应流上前后两次接受到数据的间隔,单位为毫秒。 - receiveTimeout: const Duration(milliseconds: 10000), - //Http请求头. - headers: { - 'user-agent': 'Dart/3.6 (dart:io)', // Http2Adapter不会自动添加标头 - if (!_enableHttp2) 'connection': 'keep-alive', - 'accept-encoding': 'br,gzip', - }, - responseDecoder: _responseDecoder, // Http2Adapter没有自动解压 - persistentConnection: true, - ); + static Timer? _networkChangeDebounce; + static void _watchConnectivity() { + Connectivity().onConnectivityChanged.skip(1).listen((result) { + _networkChangeDebounce?.cancel(); + _networkChangeDebounce = Timer( + const Duration(milliseconds: 500), + _resetAdaptersForNetworkChange, + ); + }); + } + static (IOHttpClientAdapter, ConnectionManager?) _createPool() { final bool enableSystemProxy; late final String systemProxyHost; late final int? systemProxyPort; @@ -160,30 +151,72 @@ class Request { ..autoUncompress = false, // Http2Adapter没有自动解压, 统一行为 ); + final connectionManager = _enableHttp2 + ? ConnectionManager( + idleTimeout: const Duration(seconds: 15), + onClientCreate: enableSystemProxy + ? (_, config) => config + ..proxy = Uri( + scheme: 'http', + host: systemProxyHost, + port: systemProxyPort, + ) + ..onBadCertificate = (_) => true + : Pref.badCertificateCallback + ? (_, config) => config.onBadCertificate = (_) => true + : null, + ) + : null; + return (http11Adapter, connectionManager); + } + + @pragma('vm:notify-debugger-on-exception') + static void _resetAdaptersForNetworkChange() { + try { + final (h11, connectionManager) = _createPool(); + if (connectionManager != null) { + (dio.httpClientAdapter as Http2Adapter) + ..connectionManager.close(force: true) + ..connectionManager = connectionManager + ..fallbackAdapter.close(force: true) + ..fallbackAdapter = h11; + _http11Dio?.httpClientAdapter = h11; + } else { + dio + ..httpClientAdapter.close(force: true) + ..httpClientAdapter = h11; + } + } catch (_) {} + } + + /* + * config it and create + */ + Request._internal() { + //BaseOptions、Options、RequestOptions 都可以配置参数,优先级别依次递增,且可以根据优先级别覆盖参数 + BaseOptions options = BaseOptions( + //请求基地址,可以包含子路径 + baseUrl: HttpString.apiBaseUrl, + //连接服务器超时时间,单位是毫秒. + connectTimeout: const Duration(milliseconds: 10000), + //响应流上前后两次接受到数据的间隔,单位为毫秒。 + receiveTimeout: const Duration(milliseconds: 10000), + //Http请求头. + headers: { + 'user-agent': 'Dart/3.6 (dart:io)', // Http2Adapter不会自动添加标头 + if (!_enableHttp2) 'connection': 'keep-alive', + 'accept-encoding': 'br,gzip', + }, + responseDecoder: _responseDecoder, // Http2Adapter没有自动解压 + persistentConnection: true, + ); + + final (h11, connectionManager) = _createPool(); + dio = Dio(options) ..httpClientAdapter = _enableHttp2 - ? Http2Adapter( - ConnectionManager( - idleTimeout: const Duration(seconds: 15), - onClientCreate: enableSystemProxy - ? (_, config) { - config - ..proxy = Uri( - scheme: 'http', - host: systemProxyHost, - port: systemProxyPort, - ) - ..onBadCertificate = (_) => true; - } - : Pref.badCertificateCallback - ? (_, config) { - config.onBadCertificate = (_) => true; - } - : null, - ), - fallbackAdapter: http11Adapter, - ) - : http11Adapter; + ? Http2Adapter(connectionManager, fallbackAdapter: h11) + : h11; // 先于其他Interceptor if (Pref.retryCount != 0) { @@ -208,6 +241,8 @@ class Request { ..options.validateStatus = (int? status) { return status != null && status >= 200 && status < 300; }; + + if (Platform.isIOS) _watchConnectivity(); } /*