Flutter网络请求进阶:数据缓存优化与网络状态感知动态适配
Flutter网络请求进阶:数据缓存优化与网络状态感知动态适配
在企业级Flutter应用中,“数据缓存的精细化控制”与“网络状态的动态适配”是提升用户体验的关键。普通缓存方案易出现数据一致性问题,而固定的网络请求策略无法适配弱网、断网等复杂网络环境。本文聚焦这两大核心痛点,提供“多级缓存架构”“缓存一致性保障”“网络状态实时感知”“动态请求策略调整”的全链路实战方案,进一步强化Flutter网络交互的稳定性与用户体验。
一、核心设计思路:缓存精准控制与网络自适应
本次方案遵循两大核心设计原则,确保功能实用性与扩展性:
-
多级缓存与精准控制原则:采用“内存缓存+磁盘缓存”多级架构,区分“永久缓存”“时效缓存”“临时缓存”,支持按接口、按数据类型配置缓存策略,同时通过版本号、时间戳保障缓存与服务端数据一致性。
-
网络感知与动态适配原则:实时监听网络状态(在线/弱网/断网、Wi-Fi/蜂窝网络),针对不同网络场景动态调整请求策略(如弱网时降低并发、增大超时时间;断网时优先读取缓存;Wi-Fi/蜂窝网络切换时重新验证缓存)。
二、数据缓存进阶:多级架构与一致性保障
传统缓存方案多为单一层级、固定时效,易导致“缓存脏数据”“重复请求”“缓存穿透”等问题。本节实现“内存+磁盘”多级缓存,支持个性化缓存策略配置,同时通过多种机制保障缓存与服务端数据一致性。
1. 基础准备:缓存模型与策略枚举
定义缓存数据模型、缓存策略枚举,明确各策略的适用场景,为后续缓存控制提供基础。
import 'dart:convert';
import 'package:intl/intl.dart';
// 缓存策略枚举
enum CacheStrategy {
permanent, // 永久缓存(如静态配置、字典数据)
timeLimited, // 时效缓存(如列表数据,需设置过期时间)
temporary, // 临时缓存(如单次请求结果,应用重启后失效)
noCache, // 不缓存(如实时性要求极高的支付、登录接口)
}
// 缓存数据模型
class CacheModel {
// 缓存数据(JSON字符串)
final String data;
// 缓存策略
final CacheStrategy strategy;
// 过期时间(仅时效缓存有效,毫秒级时间戳)
final int? expireTime;
// 数据版本号(用于一致性校验)
final String version;
// 缓存时间(毫秒级时间戳)
final int cacheTime;
CacheModel({
required this.data,
required this.strategy,
this.expireTime,
required this.version,
required this.cacheTime,
});
// 转换为Map(用于磁盘存储)
Map<String, dynamic> toMap() {
return {
'data': data,
'strategy': strategy.name,
'expireTime': expireTime,
'version': version,
'cacheTime': cacheTime,
};
}
// 从Map解析(用于读取磁盘缓存)
factory CacheModel.fromMap(Map<String, dynamic> map) {
return CacheModel(
data: map['data'] as String,
strategy: CacheStrategy.values.firstWhere(
(e) => e.name == map['strategy'],
orElse: () => CacheStrategy.noCache,
),
expireTime: map['expireTime'] as int?,
version: map['version'] as String,
cacheTime: map['cacheTime'] as int,
);
}
// 检查缓存是否有效
bool get isValid {
switch (strategy) {
case CacheStrategy.permanent:
return true; // 永久有效
case CacheStrategy.timeLimited:
final now = DateTime.now().millisecondsSinceEpoch;
return expireTime != null && now < expireTime!;
case CacheStrategy.temporary:
// 临时缓存:应用运行期间有效(此处通过缓存时间是否在当前会话内判断,实际可结合应用生命周期)
return true;
case CacheStrategy.noCache:
return false;
}
}
}
2. 实现多级缓存工具类:内存+磁盘
封装缓存工具类,管理内存缓存(LRU策略,限制最大容量)与磁盘缓存(基于Hive实现,高效读写),提供缓存增删改查、策略校验等核心方法。
import 'dart:io';
import 'package:hive/hive.dart';
import 'package:path_provider/path_provider.dart';
import 'cache_model.dart';
// LRU内存缓存(限制最大容量,淘汰最少使用的缓存)
class LruMemoryCache {
final int maxSize;
final Map<String, CacheModel> _cache = {};
final List<String> _keys = []; // 记录访问顺序,尾部为最近访问
LruMemoryCache({this.maxSize = 50});
// 获取缓存
CacheModel? get(String key) {
final model = _cache[key];
if (model != null) {
// 更新访问顺序
_keys.remove(key);
_keys.add(key);
}
return model;
}
// 存入缓存
void put(String key, CacheModel model) {
if (_cache.containsKey(key)) {
_keys.remove(key);
} else if (_cache.length >= maxSize) {
// 超过最大容量,淘汰最少使用的缓存(头部元素)
final removeKey = _keys.removeAt(0);
_cache.remove(removeKey);
}
_cache[key] = model;
_keys.add(key);
}
// 移除缓存
void remove(String key) {
_cache.remove(key);
_keys.remove(key);
}
// 清空缓存
void clear() {
_cache.clear();
_keys.clear();
}
}
// 多级缓存工具类(单例)
class CacheManager {
static final CacheManager _instance = CacheManager._internal();
factory CacheManager() => _instance;
CacheManager._internal();
// 内存缓存(LRU策略)
late LruMemoryCache _memoryCache;
// 磁盘缓存(Hive数据库)
late Box<Map<String, dynamic>> _diskCache;
// 缓存版本号(全局统一,用于批量失效缓存)
String _cacheVersion = '1.0.0';
// 初始化缓存
Future<void> init() async {
_memoryCache = LruMemoryCache(maxSize: 50);
// 初始化Hive,配置磁盘缓存路径
final dir = await getApplicationDocumentsDirectory();
Hive.init(dir.path + '/network_cache');
_diskCache = await Hive.openBox<Map<String, dynamic>>('network_cache_box');
return;
}
// 更新缓存版本号(批量失效所有缓存)
void updateCacheVersion(String newVersion) {
_cacheVersion = newVersion;
clearAllCache();
}
// 生成缓存Key(接口路径+方法+参数+版本号,确保唯一性)
String generateCacheKey({
required String path,
required String method,
Map<String, dynamic>? params,
Map<String, dynamic>? data,
}) {
final paramsStr = params != null ? json.encode(params) : '';
final dataStr = data != null ? json.encode(data) : '';
return '$_cacheVersion|$method|$path|$paramsStr|$dataStr';
}
// 存入缓存(根据策略存入内存+磁盘,或仅内存)
Future<void> saveCache({
required String key,
required dynamic data,
required CacheStrategy strategy,
int? expireSeconds, // 过期秒数(仅时效缓存有效)
}) async {
final dataStr = json.encode(data);
int? expireTime;
if (strategy == CacheStrategy.timeLimited && expireSeconds != null) {
expireTime = DateTime.now().millisecondsSinceEpoch + (expireSeconds * 1000);
}
final cacheModel = CacheModel(
data: dataStr,
strategy: strategy,
expireTime: expireTime,
version: _cacheVersion,
cacheTime: DateTime.now().millisecondsSinceEpoch,
);
// 存入内存缓存
_memoryCache.put(key, cacheModel);
// 永久缓存、时效缓存存入磁盘;临时缓存不存入磁盘
if (strategy == CacheStrategy.permanent || strategy == CacheStrategy.timeLimited) {
await _diskCache.put(key, cacheModel.toMap());
}
}
// 获取缓存(优先内存,再磁盘,校验有效性)
Future<dynamic?> getCache(String key) async {
// 1. 从内存缓存获取
final memoryCache = _memoryCache.get(key);
if (memoryCache != null && memoryCache.isValid) {
return json.decode(memoryCache.data);
}
// 2. 从磁盘缓存获取
final diskCacheMap = _diskCache.get(key);
if (diskCacheMap != null) {
final diskCache = CacheModel.fromMap(diskCacheMap);
if (diskCache.isValid && diskCache.version == _cacheVersion) {
// 存入内存缓存,提升后续访问速度
_memoryCache.put(key, diskCache);
return json.decode(diskCache.data);
} else {
// 缓存失效,移除
await _diskCache.delete(key);
}
}
return null;
}
// 移除指定缓存
Future<void> removeCache(String key) async {
_memoryCache.remove(key);
await _diskCache.delete(key);
}
// 清空所有缓存
Future<void> clearAllCache() async {
_memoryCache.clear();
await _diskCache.clear();
}
// 清空过期缓存(定期调用,如应用启动时)
Future<void> clearExpiredCache() async {
final now = DateTime.now().millisecondsSinceEpoch;
final keys = _diskCache.keys;
for (final key in keys) {
final cacheMap = _diskCache.get(key);
if (cacheMap != null) {
final cache = CacheModel.fromMap(cacheMap);
if (!cache.isValid || cache.version != _cacheVersion) {
await _diskCache.delete(key);
}
}
}
// 清空内存中失效的缓存
_memoryCache._cache.removeWhere((key, value) => !value.isValid || value.version != _cacheVersion);
}
}
3. 实现缓存拦截器:请求自动缓存与读取
通过Dio拦截器整合多级缓存工具,实现请求的自动缓存读取与写入,支持在单个请求中配置个性化缓存策略,无需手动处理缓存逻辑。
import 'dart:convert';
import 'package:dio/dio.dart';
import 'cache_manager.dart';
import 'cache_model.dart';
// 单个请求的缓存配置
class RequestCacheConfig {
// 缓存策略
final CacheStrategy strategy;
// 过期秒数(仅时效缓存有效)
final int? expireSeconds;
// 是否强制刷新(忽略缓存,直接请求服务端,请求成功后更新缓存)
final bool forceRefresh;
// 缓存key生成器(默认使用CacheManager的generateCacheKey)
final String Function(RequestOptions options)? keyGenerator;
RequestCacheConfig({
this.strategy = CacheStrategy.noCache,
this.expireSeconds,
this.forceRefresh = false,
this.keyGenerator,
});
}
// 缓存拦截器
class CacheInterceptor extends Interceptor {
final CacheManager _cacheManager = CacheManager();
@override
Future<void> onRequest(RequestOptions options, RequestInterceptorHandler handler) async {
// 1. 获取当前请求的缓存配置
final cacheConfig = options.extra['cacheConfig'] as RequestCacheConfig? ??
RequestCacheConfig(strategy: CacheStrategy.noCache);
// 2. 不缓存或强制刷新,直接放行
if (cacheConfig.strategy == CacheStrategy.noCache || cacheConfig.forceRefresh) {
handler.next(options);
return;
}
// 3. 生成缓存key
final cacheKey = cacheConfig.keyGenerator?.call(options) ??
_cacheManager.generateCacheKey(
path: options.path,
method: options.method,
params: options.queryParameters,
data: options.data,
);
// 4. 获取缓存
final cacheData = await _cacheManager.getCache(cacheKey);
if (cacheData != null) {
// 有有效缓存,直接返回缓存数据,不发起网络请求
handler.resolve(
Response(
requestOptions: options,
data: cacheData,
statusCode: 200,
),
);
return;
}
// 5. 无缓存,继续发起网络请求,并将缓存key存入extra
options.extra['cacheKey'] = cacheKey;
options.extra['cacheConfig'] = cacheConfig;
handler.next(options);
}
@override
Future<void> onResponse(Response response, ResponseInterceptorHandler handler) async {
// 1. 获取请求的缓存配置和缓存key
final cacheConfig = response.requestOptions.extra['cacheConfig'] as RequestCacheConfig?;
final cacheKey = response.requestOptions.extra['cacheKey'] as String?;
// 2. 无需缓存或无缓存key,直接放行
if (cacheConfig == null || cacheConfig.strategy == CacheStrategy.noCache || cacheKey == null) {
handler.next(response);
return;
}
// 3. 存入缓存
await _cacheManager.saveCache(
key: cacheKey,
data: response.data,
strategy: cacheConfig.strategy,
expireSeconds: cacheConfig.expireSeconds,
);
handler.next(response);
}
@override
Future<void> onError(DioException err, ErrorInterceptorHandler handler) async {
// 网络请求失败时,尝试返回缓存(仅针对GET请求)
if (err.requestOptions.method.toUpperCase() == 'GET') {
final cacheConfig = err.requestOptions.extra['cacheConfig'] as RequestCacheConfig?;
final cacheKey = err.requestOptions.extra['cacheKey'] as String?;
if (cacheConfig != null && cacheConfig.strategy != CacheStrategy.noCache && cacheKey != null) {
final cacheData = await _cacheManager.getCache(cacheKey);
if (cacheData != null) {
// 返回缓存数据,避免用户看到错误
handler.resolve(
Response(
requestOptions: err.requestOptions,
data: cacheData,
statusCode: 200,
),
);
return;
}
}
}
handler.next(err);
}
}
三、网络状态感知:实时监听与动态适配
通过监听网络状态变化,动态调整请求策略(超时时间、并发数、缓存策略、重试机制),提升弱网/断网场景下的用户体验,同时避免无效请求浪费资源。
1. 基础准备:网络状态模型与监听工具
使用connectivity_plus插件监听网络状态,定义网络状态模型,提供全局网络状态访问与变化回调。
import 'dart:async';
import 'package:connectivity_plus/connectivity_plus.dart';
// 网络类型枚举
enum NetworkType {
wifi, // Wi-Fi
mobile, // 蜂窝网络(4G/5G等)
none, // 无网络
other, // 其他网络
}
// 网络状态模型
class NetworkState {
final bool isConnected; // 是否连接网络
final NetworkType type; // 网络类型
NetworkState({
required this.isConnected,
required this.type,
});
// 弱网判断(可根据实际业务调整,如蜂窝网络且信号弱)
bool get isWeakNetwork => isConnected && type == NetworkType.mobile;
}
// 网络状态监听工具(单例)
class NetworkMonitor {
static final NetworkMonitor _instance = NetworkMonitor._internal();
factory NetworkMonitor() => _instance;
NetworkMonitor._internal();
final Connectivity _connectivity = Connectivity();
late StreamSubscription<ConnectivityResult> _subscription;
final StreamController<NetworkState> _stateController = StreamController<NetworkState>.broadcast();
late NetworkState _currentState;
// 初始化网络监听
Future<void> init() async {
// 获取初始网络状态
final result = await _connectivity.checkConnectivity();
_currentState = _mapToNetworkState(result);
_stateController.add(_currentState);
// 监听网络状态变化
_subscription = _connectivity.onConnectivityChanged.listen((result) {
_currentState = _mapToNetworkState(result);
_stateController.add(_currentState);
});
}
// 映射ConnectivityResult到NetworkState
NetworkState _mapToNetworkState(ConnectivityResult result) {
switch (result) {
case ConnectivityResult.wifi:
return NetworkState(isConnected: true, type: NetworkType.wifi);
case ConnectivityResult.mobile:
return NetworkState(isConnected: true, type: NetworkType.mobile);
case ConnectivityResult.none:
return NetworkState(isConnected: false, type: NetworkType.none);
default:
return NetworkState(isConnected: true, type: NetworkType.other);
}
}
// 获取当前网络状态
NetworkState get currentState => _currentState;
// 网络状态变化流(外部可监听)
Stream<NetworkState> get stateStream => _stateController.stream;
// 取消监听
void dispose() {
_subscription.cancel();
_stateController.close();
}
}
2. 实现网络适配拦截器:动态调整请求策略
通过Dio拦截器结合网络监听工具,根据当前网络状态动态调整请求参数(超时时间、并发数、重试策略),实现请求策略的自适应优化。
import 'package:dio/dio.dart';
import 'network_monitor.dart';
import 'retry_interceptor.dart'; // 复用之前的重试配置
// 网络适配配置(不同网络状态的策略)
class NetworkAdaptConfig {
// Wi-Fi环境配置
final Duration wifiTimeout;
final int wifiMaxRetries;
final int wifiConcurrentCapacity;
// 蜂窝网络环境配置
final Duration mobileTimeout;
final int mobileMaxRetries;
final int mobileConcurrentCapacity;
// 无网络环境配置(是否优先读取缓存)
final bool noneNetworkUseCache;
NetworkAdaptConfig({
// Wi-Fi配置
this.wifiTimeout = const Duration(milliseconds: 15000),
this.wifiMaxRetries = 3,
this.wifiConcurrentCapacity = 10,
// 蜂窝网络配置(弱网优化:更长超时,更少重试,更低并发)
this.mobileTimeout = const Duration(milliseconds: 30000),
this.mobileMaxRetries = 2,
this.mobileConcurrentCapacity = 5,
// 无网络配置
this.noneNetworkUseCache = true,
});
}
// 网络适配拦截器
class NetworkAdaptInterceptor extends Interceptor {
final NetworkMonitor _networkMonitor = NetworkMonitor();
final NetworkAdaptConfig _adaptConfig;
final ConcurrentControlInterceptor _concurrentInterceptor; // 并发控制拦截器实例
NetworkAdaptInterceptor({
required NetworkAdaptConfig adaptConfig,
required ConcurrentControlInterceptor concurrentInterceptor,
}) : _adaptConfig = adaptConfig,
_concurrentInterceptor = concurrentInterceptor {
// 监听网络状态变化,动态调整并发控制速率
_networkMonitor.stateStream.listen((state) {
_adjustConcurrentRate(state);
});
}
@override
void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
final networkState = _networkMonitor.currentState;
// 1. 无网络时,强制使用缓存(覆盖请求的缓存配置)
if (!networkState.isConnected) {
final originalCacheConfig = options.extra['cacheConfig'] as RequestCacheConfig? ??
RequestCacheConfig(strategy: CacheStrategy.noCache);
options.extra['cacheConfig'] = originalCacheConfig.copyWith(
forceRefresh: false, // 禁止强制刷新
strategy: originalCacheConfig.strategy == CacheStrategy.noCache
? CacheStrategy.temporary // 无缓存策略时,临时启用临时缓存
: originalCacheConfig.strategy,
);
}
// 2. 动态调整超时时间
options.connectTimeout = _getTimeoutByNetworkState(networkState);
options.sendTimeout = options.connectTimeout;
options.receiveTimeout = options.connectTimeout;
// 3. 动态调整重试策略
final originalRetryConfig = options.extra['retryConfig'] as RetryConfig? ??
const RetryConfig();
options.extra['retryConfig'] = originalRetryConfig.copyWith(
maxRetries: _getMaxRetriesByNetworkState(networkState),
);
handler.next(options);
}
// 根据网络状态获取超时时间
Duration _getTimeoutByNetworkState(NetworkState state) {
if (!state.isConnected) {
return const Duration(milliseconds: 5000); // 无网络时,快速结束请求,优先读缓存
}
switch (state.type) {
case NetworkType.wifi:
return _adaptConfig.wifiTimeout;
case NetworkType.mobile:
return _adaptConfig.mobileTimeout;
default:
return _adaptConfig.wifiTimeout;
}
}
// 根据网络状态获取最大重试次数
int _getMaxRetriesByNetworkState(NetworkState state) {
if (!state.isConnected) {
return 0; // 无网络时不重试
}
switch (state.type) {
case NetworkType.wifi:
return _adaptConfig.wifiMaxRetries;
case NetworkType.mobile:
return _adaptConfig.mobileMaxRetries;
default:
return _adaptConfig.wifiMaxRetries;
}
}
// 根据网络状态调整并发控制速率
void _adjustConcurrentRate(NetworkState state) {
if (!state.isConnected) {
_concurrentInterceptor.adjustTokenRate(0); // 无网络时,暂停并发请求
return;
}
switch (state.type) {
case NetworkType.wifi:
_concurrentInterceptor.adjustTokenRate(_adaptConfig.wifiConcurrentCapacity / 2);
break;
case NetworkType.mobile:
_concurrentInterceptor.adjustTokenRate(_adaptConfig.mobileConcurrentCapacity / 2);
break;
default:
_concurrentInterceptor.adjustTokenRate(_adaptConfig.wifiConcurrentCapacity / 2);
}
}
}
3. 整合所有组件:构建自适应网络请求体系
将多级缓存拦截器、网络适配拦截器与之前的加密、并发控制、重试、异常监控拦截器整合,形成完整的“缓存优化+网络自适应”高级网络体系。
import 'package:dio/dio.dart';
import 'cache_interceptor.dart';
import 'network_adapt_interceptor.dart';
import 'concurrent_control_interceptor.dart';
import 'retry_interceptor.dart';
import 'exception_monitor_interceptor.dart';
import 'encrypt_interceptor.dart';
import 'env_manager.dart';
import 'cache_manager.dart';
import 'network_monitor.dart';
class AdaptiveNetworkUtil {
static final AdaptiveNetworkUtil _instance = AdaptiveNetworkUtil._internal();
factory AdaptiveNetworkUtil() => _instance;
late Dio _dio;
late EnvManager _envManager;
late CacheManager _cacheManager;
late NetworkMonitor _networkMonitor;
late ConcurrentControlInterceptor _concurrentInterceptor;
AdaptiveNetworkUtil._internal() {
_envManager = EnvManager();
_cacheManager = CacheManager();
_networkMonitor = NetworkMonitor();
_concurrentInterceptor = ConcurrentControlInterceptor(defaultEnableLimit: true);
// 初始化核心组件
_initCoreComponents();
}
// 初始化核心组件(缓存、网络监听、环境配置)
Future<void> _initCoreComponents() async {
await _envManager.init();
await _cacheManager.init();
await _cacheManager.clearExpiredCache(); // 清除过期缓存
await _networkMonitor.init();
_initDio();
}
// 初始化Dio(整合所有拦截器)
void _initDio() {
_dio = Dio();
final envConfig = _envManager.currentConfig;
// 1. 异常监控拦截器(最先添加,捕获所有异常)
_dio.interceptors.add(ExceptionMonitorInterceptor(
config: ExceptionMonitorConfig(
enableLocalLog: envConfig.enableLog,
enableRemoteReport: true,
reportLevelThreshold: ExceptionLevel.warning,
onReport: (exception) async {
await _dio.post(
envConfig.exceptionReportUrl,
data: exception.toJson(),
options: Options(extra: {
'concurrentControl': ConcurrentControlConfig(skipLimit: true),
'cacheConfig': RequestCacheConfig(strategy: CacheStrategy.noCache),
}),
);
},
),
));
// 2. 缓存拦截器(第二添加,优先读取缓存)
_dio.interceptors.add(CacheInterceptor());
// 3. 网络适配拦截器(调整请求策略)
_dio.interceptors.add(NetworkAdaptInterceptor(
adaptConfig: NetworkAdaptConfig(
// Wi-Fi配置
wifiTimeout: const Duration(milliseconds: 15000),
wifiMaxRetries: 3,
wifiConcurrentCapacity: 10,
// 蜂窝网络配置
mobileTimeout: const Duration(milliseconds: 30000),
mobileMaxRetries: 2,
mobileConcurrentCapacity: 5,
// 无网络配置
noneNetworkUseCache: true,
),
concurrentInterceptor: _concurrentInterceptor,
));
// 4. 并发控制拦截器
_dio.interceptors.add(_concurrentInterceptor);
// 5. 加密拦截器
_dio.interceptors.add(EncryptInterceptor(
config: EncryptInterceptorConfig(
enableEncrypt: envConfig.enableEncrypt,
signSecret: envConfig.signSecret,
skipEncryptPaths: envConfig.skipEncryptPaths,
),
));
// 6. 重试拦截器(最后添加,捕获前面拦截器的异常并重试)
_dio.interceptors.add(RetryInterceptor(
defaultRetryConfig: const RetryConfig(),
));
// 基础配置
_dio.options.baseUrl = envConfig.baseUrl;
_dio.options.connectTimeout = const Duration(milliseconds: 15000);
}
// 对外提供请求方法(支持缓存、并发、重试等配置)
Future<T?> request<T>(
String path, {
required String method,
Map<String, dynamic>? queryParams,
dynamic data,
Options? options,
RequestCacheConfig? cacheConfig,
ConcurrentControlConfig? concurrentControl,
RetryConfig? retryConfig,
bool skipEncrypt = false,
}) async {
final extra = <String, dynamic>{};
if (cacheConfig != null) extra['cacheConfig'] = cacheConfig;
if (concurrentControl != null) extra['concurrentControl'] = concurrentControl;
if (retryConfig != null) extra['retryConfig'] = retryConfig;
if (skipEncrypt) extra['skipEncrypt'] = true;
final requestOptions = Options(
method: method,
...options,
extra: {
...options?.extra ?? {},
...extra,
},
);
try {
final response = await _dio.request(
path,
queryParameters: queryParams,
data: data,
options: requestOptions,
);
return response.data as T?;
} catch (e) {
if (envConfig.enableLog) {
print('请求失败:$e');
}
rethrow;
}
}
// 封装GET请求(默认启用时效缓存,过期时间30秒)
Future<T?> get<T>(
String path, {
Map<String, dynamic>? queryParams,
Options? options,
RequestCacheConfig? cacheConfig = const RequestCacheConfig(
strategy: CacheStrategy.timeLimited,
expireSeconds: 30,
),
ConcurrentControlConfig? concurrentControl,
RetryConfig? retryConfig,
bool skipEncrypt = false,
}) =>
request<T>(
path,
method: 'GET',
queryParams: queryParams,
options: options,
cacheConfig: cacheConfig,
concurrentControl: concurrentControl,
retryConfig: retryConfig,
skipEncrypt: skipEncrypt,
);
// 封装POST请求(默认不缓存)
Future<T?> post<T>(
String path, {
dynamic data,
Map<String, dynamic>? queryParams,
Options? options,
RequestCacheConfig? cacheConfig = const RequestCacheConfig(strategy: CacheStrategy.noCache),
ConcurrentControlConfig? concurrentControl,
RetryConfig? retryConfig,
bool skipEncrypt = false,
}) =>
request<T>(
path,
method: 'POST',
data: data,
queryParams: queryParams,
options: options,
cacheConfig: cacheConfig,
concurrentControl: concurrentControl,
retryConfig: retryConfig,
skipEncrypt: skipEncrypt,
);
// 对外提供缓存操作方法
Future<void> clearAllCache() => _cacheManager.clearAllCache();
Future<void> updateCacheVersion(String newVersion) => _cacheManager.updateCacheVersion(newVersion);
// 对外提供网络状态访问
NetworkState get currentNetworkState => _networkMonitor.currentState;
Stream<NetworkState> get networkStateStream => _networkMonitor.stateStream;
}
final adaptiveNetUtil = AdaptiveNetworkUtil();
四、实战场景:典型业务场景的配置示例
针对不同业务场景,给出个性化的网络请求配置示例,帮助开发者快速落地。
1. 场景1:首页列表数据(弱网优先缓存,Wi-Fi自动刷新)
// 监听网络状态,Wi-Fi时强制刷新,弱网/断网时读取缓存
Future<void> loadHomeList() async {
final networkState = adaptiveNetUtil.currentNetworkState;
try {
final listData = await adaptiveNetUtil.get<List<dynamic>>(
'/api/home/list',
cacheConfig: RequestCacheConfig(
strategy: CacheStrategy.timeLimited,
expireSeconds: 60, // 缓存1分钟
forceRefresh: networkState.type == NetworkType.wifi, // Wi-Fi时强制刷新
),
retryConfig: RetryConfig(
maxRetries: networkState.isWeakNetwork ? 1 : 3, // 弱网时减少重试
),
);
// 渲染列表
} catch (e) {
// 异常处理(无网络时已优先返回缓存,此处仅处理缓存不存在的情况)
print('加载首页列表失败:$e');
}
}
2. 场景2:静态配置数据(永久缓存,版本更新时失效)
// 加载静态配置(如地区列表、字典数据)
Future<void> loadStaticConfig() async {
try {
final configData = await adaptiveNetUtil.get<Map<String, dynamic>>(
'/api/config/static',
cacheConfig: RequestCacheConfig(
strategy: CacheStrategy.permanent, // 永久缓存
),
);
// 使用配置数据
} catch (e) {
print('加载静态配置失败:$e');
}
}
// 应用版本更新时,更新缓存版本号,批量失效永久缓存
void onAppVersionUpdated(String newAppVersion) {
adaptiveNetUtil.updateCacheVersion(newAppVersion);
}
3. 场景3:实时支付接口(不缓存,弱网增大超时)
// 支付请求(实时性极高,不缓存,弱网时增大超时)
Future<void> submitPayment(Map<String, dynamic> paymentData) async {
final networkState = adaptiveNetUtil.currentNetworkState;
try {
final result = await adaptiveNetUtil.post<Map<String, dynamic>>(
'/api/payment/submit',
data: paymentData,
cacheConfig: RequestCacheConfig(strategy: CacheStrategy.noCache), // 不缓存
retryConfig: RetryConfig(enableRetry: false), // 不重试(避免重复支付)
options: Options(
sendTimeout: networkState.isWeakNetwork
? const Duration(milliseconds: 60000) // 弱网时超时60秒
: const Duration(milliseconds: 30000),
),
);
// 处理支付结果
} catch (e) {
print('支付请求失败:$e');
// 提示用户检查网络或重试
}
}
五、结语:构建自适应、高可用的网络交互层
本文提出的“多级缓存优化+网络状态感知动态适配”方案,聚焦数据一致性与复杂网络环境适配两大核心痛点,与此前的“加密、并发控制、异常监控、多环境适配、断点续传”共同构成了覆盖全场景的Flutter高级网络体系。通过精细化的缓存策略配置、实时的网络状态监听与动态的请求参数调整,能够有效提升应用在弱网、断网等极端场景下的可用性,同时减少无效网络请求,降低服务端压力。
实际开发中,需结合业务特性灵活调整配置:例如内容类应用可强化缓存策略,提升离线阅读体验;金融类应用需严格控制缓存范围,确保交易数据的实时性与安全性;社交类应用可优化弱网下的重试与并发策略,提升消息收发的稳定性。通过本文的实战方案,开发者可快速搭建自适应、高可用的网络交互层,为用户提供流畅、稳定的网络体验,同时降低后期维护成本。
欢迎大家加入开源鸿蒙跨平台开发者社区,一起共建开源鸿蒙跨平台生态。
更多推荐




所有评论(0)