当前位置: 首页 > news >正文

网站首页像素鸿鹄网站建设

网站首页像素,鸿鹄网站建设,计算机网站设计论文,西安专业做网站的Flutter中的网络请求图片存储为缓存#xff0c;与定制删除本地缓存 1#xff1a;封装请求图片函数 2#xff1a;访问的图片都会转为本地缓存#xff0c;当相同的请求url#xff0c;会在本地调用图片 3#xff1a;本地缓存管理【windows与andriod已经测试】【有页面】【有…Flutter中的网络请求图片存储为缓存与定制删除本地缓存 1封装请求图片函数 2访问的图片都会转为本地缓存当相同的请求url会在本地调用图片 3本地缓存管理【windows与andriod已经测试】【有页面】【有调用案例】 4删除本地缓存 清理缓存页面下方代码中已包括 windows中显示图片-----------安卓中显示图片 这里还没有进行优化图片显示的宽高圆角请自行设置 打印日志显示图片请求的获取过程与报错原因 TuPianJiaZai 图片加载工具使用教程 注意事项 imageUrl 可以为 null此时会显示空白图片会自动缓存到本地支持自动重试3次默认有加载动画和错误提示支持所有标准图片格式 实际应用场景 商品展示卡片用户头像图片列表背景图片Banner图片 1. 基本用法 1.1导入文件 import ../utils/get_images/tupianjiazai.dart;TuPianJiaZai.jiazaiTupian(imageUrl: product.image,width: double.infinity,height: 200,fit: BoxFit.cover, )2. 完整参数说明 TuPianJiaZai.jiazaiTupian(// 必需参数imageUrl: String?, // 图片URL可以为null// 可选参数width: double?, // 显示宽度height: double?, // 显示高度fit: BoxFit, // 图片填充方式默认BoxFit.covercacheWidth: int?, // 缓存图片宽度用于优化内存cacheHeight: int?, // 缓存图片高度用于优化内存placeholder: Widget?, // 加载时显示的占位WidgeterrorWidget: Widget?, // 加载失败时显示的Widget )3. 使用案例 3.1 基础加载 TuPianJiaZai.jiazaiTupian(imageUrl: https://example.com/image.jpg,width: 200,height: 200, )3.2 自定义占位图和错误图 TuPianJiaZai.jiazaiTupian(imageUrl: imageUrl,width: 300,height: 200,placeholder: const Center(child: CircularProgressIndicator(),), errorWidget: const Center(child: Column(mainAxisAlignment: MainAxisAlignment.center,children: [Icon(Icons.error),Text(加载失败),],),), )3.3 列表项中使用 ListView.builder( itemBuilder: (context, index) { return TuPianJiaZai.jiazaiTupian( imageUrl: imageUrls[index], height: 150, fit: BoxFit.cover, cacheWidth: 600, // 优化缓存大小 cacheHeight: 400, ); }, )请自行在\lib\utils\get_images\文件夹中创建一下配置 D:\F\luichun\lib\utils\get_images\huancunguanli.dart import dart:io; import dart:typed_data; import package:path_provider/path_provider.dart; import package:crypto/crypto.dart; import dart:convert; import package:shared_preferences/shared_preferences.dart; import package:synchronized/synchronized.dart; import logger.dart; // 使用统一的日志管理器 import ../env_config.dart;// 本地进行开发时使用 会对 localhost:10005 进行请求但是安卓模拟器需要把localhost转换为 10.0.2.2/// 完整工作流程 /// 1.应用启动 - 初始化缓存目录 /// 2.请求图片 - 检查缓存 - 返回缓存或null /// 3.下载图片 - 保存图片 - 更新映射关系 /// 4.定期维护 - 清理缓存/计算大小/// 图片缓存管理器 /// 用于管理图片的本地缓存减少重复的网络请求 class HuanCunGuanLi {/// 单例模式/// 使用工厂构造函数确保全局只有一个缓存管理器实例/// 避免重复创建缓存目录和资源浪费static final HuanCunGuanLi _instance HuanCunGuanLi._internal();/// 缓存目录Directory? _cacheDir;/// 初始化锁final _lock Lock();/// 初始化标志bool _isInitialized false;/// 持久化存储的键名static const String _prefKey image_cache_urls;// 工厂构造函数factory HuanCunGuanLi() {return _instance;}// 私有构造函数HuanCunGuanLi._internal();/// 确保已初始化Futurevoid _ensureInitialized() async {if (_isInitialized) return; // 快速检查await _lock.synchronized(() async {if (_isInitialized) return; // 双重检查await init();});}/// 初始化缓存目录Futurevoid init() async {try {final appDir await getApplicationDocumentsDirectory();final cacheDir Directory(${appDir.path}/image_cache);if (!await cacheDir.exists()) {await cacheDir.create(recursive: true);}_cacheDir cacheDir;_isInitialized true;if (EnvConfig.isDevelopment) {ImageLogger.logCacheInfo(缓存系统初始化完成: ${_cacheDir!.path});}} catch (e) {ImageLogger.logCacheError(缓存系统初始化失败, error: e);rethrow;}}/// 3异步获取缓存图片/// 参数:/// url: 图片的网络地址/// 返回:/// Uint8List?: 图片的二进制数据不存在时返回null/// 流程:/// 1. 根据URL生成缓存键/// 2. 查找本地缓存文件/// 3. 返回缓存数据或nullFutureUint8List? huoquTupian(String url) async {await _ensureInitialized();try {final cacheKey _shengchengKey(url);final cacheFile File(${_cacheDir!.path}/$cacheKey);if (await cacheFile.exists()) {ImageLogger.logCacheDebug(从缓存加载图片, {url: url});return await cacheFile.readAsBytes();}return null;} catch (e) {ImageLogger.logCacheError(读取缓存图片失败, error: e);return null;}}/// 异步保存图片到缓存/// [url] 图片URL/// [imageBytes] 图片二进制数据Futurevoid baocunTupian(String url, Uint8List imageBytes) async {await _ensureInitialized();final cacheKey _shengchengKey(url);final cacheFile File(${_cacheDir!.path}/$cacheKey);await cacheFile.writeAsBytes(imageBytes);await _baocunURLyingshe(url, cacheKey);}/// 生成缓存键/// 使用MD5加密URL生成唯一标识String _shengchengKey(String url) {final bytes utf8.encode(url);final digest md5.convert(bytes);return digest.toString();}/// 4. URL 映射管理/// 保存URL映射关系/// 实现:/// 1. 获取SharedPreferences实例/// 2. 读取现有映射/// 3. 更新映射关系/// 4. 序列化并保存/// 使用 SharedPreferences 持久化存储 URL 映射关系/// JSON 序列化保存映射数据/// 异步操作避免阻塞主线程/// 保存URL映射关系Futurevoid _baocunURLyingshe(String url, String cacheKey) async {final prefs await SharedPreferences.getInstance();final MapString, String urlMap await _huoquURLyingshe();urlMap[url] cacheKey;await prefs.setString(_prefKey, jsonEncode(urlMap));}/// 获取URL映射关系FutureMapString, String _huoquURLyingshe() async {final prefs await SharedPreferences.getInstance();final String? mapJson prefs.getString(_prefKey);if (mapJson ! null) {return MapString, String.from(jsonDecode(mapJson));}return {};}/// 5.缓存清理功能/// 清除所有缓存/// 使用场景:/// 1. 应用清理存储空间/// 2. 图片资源更新/// 3. 缓存出现问题时重置/// 递归删除缓存目录/// 清除 URL 映射数据/// 清除所有缓存Futurevoid qingchuHuancun() async {await _cacheDir!.delete(recursive: true);await _cacheDir!.create();final prefs await SharedPreferences.getInstance();await prefs.remove(_prefKey);}///6 .缓存大小计算///- 异步遍历缓存目录/// 累计所有文件大小/// 使用 Stream 处理大目录/// 获取缓存大小字节Futureint huoquHuancunDaxiao() async {int size 0;await for (final file in _cacheDir!.list()) {if (file is File) {size await file.length();}}return size;} }D:\F\luichun\lib\utils\get_images\logger.dart import package:logger/logger.dart;/// 图片加载系统的日志管理器 class ImageLogger {static final Logger _logger Logger(printer: PrettyPrinter(methodCount: 0,errorMethodCount: 8,lineLength: 120,colors: true,printEmojis: true,dateTimeFormat: DateTimeFormat.onlyTimeAndSinceStart,),);// 缓存系统日志static void logCacheInfo(String message) {_logger.i( $message);}static void logCacheError(String message, {dynamic error}) {_logger.e( $message, error: error);}static void logCacheDebug(String message, [MapString, dynamic? data]) {if (data ! null) {_logger.d( $message\n${_formatData(data)});} else {_logger.d( $message);}}// 图片加载日志static void logImageInfo(String message) {_logger.i(️ $message);}static void logImageError(String message, {dynamic error}) {_logger.e(️ $message, error: error);}static void logImageDebug(String message, [MapString, dynamic? data]) {if (data ! null) {_logger.d(️ $message\n${_formatData(data)});} else {_logger.d(️ $message);}}static void logImageWarning(String message, [MapString, dynamic? data]) {if (data ! null) {_logger.w(️ $message\n${_formatData(data)});} else {_logger.w(️ $message);}}// 格式化数据为字符串static String _formatData(MapString, dynamic data) {return data.entries.map((e) ${e.key}: ${e.value}).join(\n);} } D:\F\luichun\lib\utils\get_images\qinglihuancun.dart // import package:flutter/material.dart; import huancunguanli.dart; import logger.dart;/// 缓存清理管理器 class QingLiHuanCun {static final HuanCunGuanLi _huancun HuanCunGuanLi();/// 清理所有缓存static Futurevoid qingliSuoyou() async {try {await _huancun.qingchuHuancun();ImageLogger.logCacheInfo(缓存清理完成);} catch (e) {ImageLogger.logCacheError(缓存清理失败, error: e);}}/// 获取当前缓存大小static FutureString huoquDaxiao() async {try {final size await _huancun.huoquHuancunDaxiao();// 转换为合适的单位if (size 1024) return $size B;if (size 1024 * 1024) return ${(size / 1024).toStringAsFixed(2)} KB;return ${(size / (1024 * 1024)).toStringAsFixed(2)} MB;} catch (e) {ImageLogger.logCacheError(获取缓存大小失败, error: e);return 未知;}}/// 检查缓存大小并在超过阈值时清理static Futurevoid jianchaHeQingli() async {try {final size await _huancun.huoquHuancunDaxiao();// 如果缓存超过550MB则清理if (size 550 * 1024 * 1024) {await qingliSuoyou();}} catch (e) {ImageLogger.logCacheError(缓存检查失败, error: e);}} } D:\F\luichun\lib\utils\get_images\qinglihuancundeanniu.dart import package:flutter/material.dart; import package:flutter/services.dart; import dart:async; import qinglihuancun.dart;/// 缓存配置 class CacheConfig {// 警告阈值 (当缓存超过500MB时显示警告)static const double warningThresholdMB 500.0;// 自动清理阈值static const double autoCleanThresholdMB 550.0;// 动画时长static const Duration animationDuration Duration(milliseconds: 300);// 提示显示时长static const Duration snackBarDuration Duration(seconds: 3);// 刷新动画时长static const Duration refreshAnimationDuration Duration(milliseconds: 200); }/// 清理完成回调 typedef OnCleanComplete void Function(bool success);/// 缓存监听器 class CacheListener {static final ListVoidCallback _listeners [];static void addListener(VoidCallback listener) {_listeners.add(listener);}static void removeListener(VoidCallback listener) {_listeners.remove(listener);}static void notifyListeners() {for (var listener in _listeners) {listener();}} }/// 自动清理调度器 class AutoCleanScheduler {static Timer? _timer;// 每24小时自动检查一次static void startSchedule() {_timer?.cancel();_timer Timer.periodic(const Duration(hours: 24),(_) QingLiHuanCun.jianchaHeQingli(),);}static void stopSchedule() {_timer?.cancel();_timer null;} }/// 缓存管理页面 class CacheManagementScreen extends StatelessWidget {const CacheManagementScreen({super.key});overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text(缓存管理),elevation: 0,),body: const SingleChildScrollView(child: QingLiHuanCunAnNiu(),),);} }/// 缓存清理按钮组件 class QingLiHuanCunAnNiu extends StatefulWidget {final OnCleanComplete? onCleanComplete;const QingLiHuanCunAnNiu({super.key,this.onCleanComplete,});overrideStateQingLiHuanCunAnNiu createState() _QingLiHuanCunAnNiuState(); }class _QingLiHuanCunAnNiuState extends StateQingLiHuanCunAnNiu {String _cacheSize 计算中...;bool _isClearing false;Timer? _autoCheckTimer;DateTime? _lastClickTime;bool _isDoubleClick false;overridevoid initState() {super.initState();_initializeCache();}overridevoid dispose() {_autoCheckTimer?.cancel();AutoCleanScheduler.stopSchedule();super.dispose();}// 初始化缓存Futurevoid _initializeCache() async {await _huoquDaxiao();_startAutoCheck();AutoCleanScheduler.startSchedule();}// 启动自动检查// 每30分钟检查一次缓存大小void _startAutoCheck() {_autoCheckTimer?.cancel();_autoCheckTimer Timer.periodic(const Duration(minutes: 30),(_) _huoquDaxiao(),);}// 显示错误信息void _showError(String message) {if (!mounted) return;ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Row(children: [const Icon(Icons.error_outline, color: Colors.white),const SizedBox(width: 12),Expanded(child: Text(message)),],),backgroundColor: Colors.red,behavior: SnackBarBehavior.floating,duration: CacheConfig.snackBarDuration,shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8),),),);}// 显示警告信息void _showWarning() {if (!mounted) return;ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Row(children: [const Icon(Icons.warning_amber_rounded, color: Colors.white),const SizedBox(width: 12),const Expanded(child: Text(缓存较大建议清理)),],),backgroundColor: Colors.orange,duration: CacheConfig.snackBarDuration,behavior: SnackBarBehavior.floating,shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8),),),);}// 获取缓存大小并检查Futurevoid _huoquDaxiao() async {try {final size await QingLiHuanCun.huoquDaxiao();if (!mounted) return;setState(() _cacheSize size);_checkCacheWarning(size);CacheListener.notifyListeners();} catch (e) {_showError(获取缓存大小失败: $e);}}// 检查缓存大小并显示警告void _checkCacheWarning(String size) {if (!size.contains(MB)) return;try {final double sizeInMB double.parse(size.split( )[0]);if (sizeInMB CacheConfig.warningThresholdMB) {_showWarning();}} catch (e) {// 解析错误处理}}// 显示清理进度void _showCleaningProgress() {if (!mounted) return;ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Row(children: [const SizedBox(width: 20,height: 20,child: CircularProgressIndicator(strokeWidth: 2,valueColor: AlwaysStoppedAnimationColor(Colors.white),),),const SizedBox(width: 16),const Text(正在清理缓存...),],),duration: const Duration(seconds: 1),behavior: SnackBarBehavior.floating,shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8),),),);}// 检查是否是快速双击bool _checkDoubleClick() {final now DateTime.now();if (_lastClickTime ! null) {final difference now.difference(_lastClickTime!);if (difference.inMilliseconds 1000) { // 1秒内的双击_isDoubleClick true;return true;}}_lastClickTime now;_isDoubleClick false;return false;}// 修改确认对话框逻辑Futurebool _showConfirmDialog() async {if (_isClearing) return false; // 防止重复清理// 检查是否是快速双击final isDoubleClick _checkDoubleClick();// 如果不是双击且缓存小于100MB显示无需清理提示if (!isDoubleClick _cacheSize.contains(MB)) {try {final double sizeInMB double.parse(_cacheSize.split( )[0]);if (sizeInMB 100.0) {// 显示缓存较小的提示if (mounted) {ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Row(children: [const Icon(Icons.info_outline, color: Colors.white),const SizedBox(width: 12),const Expanded(child: Text(缓存小于100MB暂无需清理\n(快速双击可强制清理)),),],),backgroundColor: Colors.blue,behavior: SnackBarBehavior.floating,duration: const Duration(seconds: 2),shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8),),),);}return false;}} catch (e) {// 解析错误处理}}// 原有的确认对话框逻辑HapticFeedback.mediumImpact();final bool? confirm await showDialogbool(context: context,builder: (context) AlertDialog(title: Row(children: [const Icon(Icons.delete_outline, color: Colors.red),const SizedBox(width: 12),Text(_isDoubleClick ? 强制清理 : 确认清理),],),content: Column(mainAxisSize: MainAxisSize.min,crossAxisAlignment: CrossAxisAlignment.start,children: [Text(当前缓存大小: $_cacheSize),const SizedBox(height: 8),Text(_isDoubleClick ? 您选择了强制清理确定要清理所有缓存吗: 清理后将需要重新下载图片确定要清理吗),],),actions: [TextButton(onPressed: () {HapticFeedback.lightImpact();Navigator.pop(context, false);},child: const Text(取消),),TextButton(onPressed: () {HapticFeedback.lightImpact();Navigator.pop(context, true);},style: TextButton.styleFrom(foregroundColor: Colors.red,),child: Text(_isDoubleClick ? 强制清理 : 清理),),],),);return confirm ?? false;}// 清理缓存Futurevoid _qingliHuancun() async {final bool confirmed await _showConfirmDialog();if (!confirmed) return;setState(() _isClearing true);try {_showCleaningProgress();await QingLiHuanCun.qingliSuoyou();if (mounted) {ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Row(children: [const Icon(Icons.check_circle_outline, color: Colors.white),const SizedBox(width: 12),const Text(缓存清理完成),],),backgroundColor: Colors.green,behavior: SnackBarBehavior.floating,shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8),),),);await _huoquDaxiao();widget.onCleanComplete?.call(true);}} catch (e) {if (mounted) {_showError(清理失败: $e);widget.onCleanComplete?.call(false);}} finally {if (mounted) {setState(() _isClearing false);}}}overrideWidget build(BuildContext context) {return Padding(padding: const EdgeInsets.all(16.0),child: Column(crossAxisAlignment: CrossAxisAlignment.stretch,children: [// 显示缓存大小Card(elevation: 0,shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12),side: BorderSide(color: Colors.grey.withOpacity(0.2),),),child: Padding(padding: const EdgeInsets.all(16.0),child: Column(crossAxisAlignment: CrossAxisAlignment.start,children: [const Text(缓存大小,style: TextStyle(fontSize: 16,fontWeight: FontWeight.bold,),),const SizedBox(height: 8),Row(mainAxisAlignment: MainAxisAlignment.spaceBetween,children: [Text(_cacheSize,style: const TextStyle(fontSize: 24,fontWeight: FontWeight.bold,),),IconButton(icon: AnimatedRotation(duration: CacheConfig.refreshAnimationDuration,turns: _isClearing ? 1 : 0,child: const Icon(Icons.refresh),),onPressed: _isClearing ? null : () async {try {setState(() _isClearing true);HapticFeedback.lightImpact();// 显示刷新提示ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Row(children: [SizedBox(width: 16,height: 16,child: CircularProgressIndicator(strokeWidth: 2,valueColor: AlwaysStoppedAnimationColor(Colors.white),),),SizedBox(width: 12),Text(正在刷新...),],),duration: Duration(milliseconds: 200),behavior: SnackBarBehavior.floating,),);await _huoquDaxiao();} finally {if (mounted) {setState(() _isClearing false);}}},),],),],),),),const SizedBox(height: 16),// 清理按钮AnimatedContainer(duration: CacheConfig.animationDuration,transform: Matrix4.translationValues(0, _isClearing ? 4 : 0, 0,),child: ElevatedButton(onPressed: _isClearing ? null : () {HapticFeedback.mediumImpact();_qingliHuancun();},style: ElevatedButton.styleFrom(padding: const EdgeInsets.symmetric(vertical: 16),shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12),),),child: _isClearing? const SizedBox(width: 20,height: 20,child: CircularProgressIndicator(strokeWidth: 2),): const Text(清理缓存,style: TextStyle(fontSize: 16),),),),const SizedBox(height: 16),// 自动清理设置Card(elevation: 0,shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12),side: BorderSide(color: Colors.grey.withOpacity(0.2),),),child: ListTile(leading: const Icon(Icons.auto_delete),title: const Text(自动清理),subtitle: Text(当缓存超过${CacheConfig.autoCleanThresholdMB}MB时自动清理),trailing: const Icon(Icons.chevron_right),onTap: _isClearing ? null : () async {HapticFeedback.lightImpact();await QingLiHuanCun.jianchaHeQingli();await _huoquDaxiao();},),),],),);} } D:\F\luichun\lib\utils\get_images\tupianjiazai.dart import package:flutter/material.dart; import package:dio/dio.dart; import dart:typed_data; import huancunguanli.dart; import ../env_config.dart; import dart:isolate; import logger.dart;/// 图片加载器类 /// 功能处理异步图片加载、缓存和显示 /// 工作流程 /// 1. 接收图片URL请求 /// 2. 检查本地缓存 /// 3. 如无缓存则在独立isolate中下载 /// 4. 下载完成后保存到缓存 /// 5. 返回图片数据用于显示 class TuPianJiaZai {static final HuanCunGuanLi _huancun HuanCunGuanLi();static bool _initialized false;/// 内部初始化方法/// 确保只初始化一次static Futurevoid _ensureInitialized() async {if (!_initialized) {await _huancun.init();_initialized true;ImageLogger.logCacheInfo(图片加载系统初始化完成);}}/// 网络请求客户端配置/// 功能配置网络请求的基本参数/// 参数说明/// - connectTimeout: 连接超时时间/// - receiveTimeout: 接收超时时间/// - headers: 请求头配置/// - followRedirects: 是否跟随重定向/// - maxRedirects: 最大重定向次数/// - validateStatus: 状态验证函数static final Dio _dio Dio(BaseOptions(connectTimeout: const Duration(seconds: 30),receiveTimeout: const Duration(seconds: 60),sendTimeout: const Duration(seconds: 30),headers: {Accept: image/webp,image/apng,image/*,*/*;q0.8,Accept-Encoding: gzip, deflate,Connection: keep-alive,},followRedirects: true,maxRedirects: 5,validateStatus: (status) status ! null status 500,responseType: ResponseType.bytes,receiveDataWhenStatusError: true,));/// 在独立isolate中加载图片/// 功能创建新的isolate来处理图片下载避免阻塞主线程/// 参数/// url: 图片的网络地址/// 返回/// Uint8List?: 图片的二进制数据下载失败返回null/// 工作流程/// 1. 创建ReceivePort接收数据/// 2. 启动新isolate处理下载/// 3. 等待结果返回static FutureUint8List? _loadInIsolate(String url) async {final receivePort ReceivePort();await Isolate.spawn(_isolateFunction, {url: url,sendPort: receivePort.sendPort,});final result await receivePort.first;return result as Uint8List?;}/// Isolate工作函数/// 功能在独立isolate中执行图片下载/// 参数/// data: 包含url和sendPort的Map/// 工作流程/// 1. 解析传入参数/// 2. 执行图片下载/// 3. 通过sendPort返回结果static void _isolateFunction(MapString, dynamic data) async {final String url data[url];final SendPort sendPort data[sendPort];try {ImageLogger.logImageDebug(开始下载图片, {url: url});int retryCount 3;ResponseListint? response;while (retryCount 0) {try {response await _dio.getListint(EnvConfig.getImageUrl(url),options: Options(responseType: ResponseType.bytes,headers: {Range: bytes0-,Connection: keep-alive,},),onReceiveProgress: (received, total) {if (EnvConfig.isDevelopment) {ImageLogger.logImageDebug(下载进度, {received: received, total: total});}},);break;} catch (e) {retryCount--;if (retryCount 0) {ImageLogger.logImageWarning(图片下载失败准备重试, {url: url,remainingRetries: retryCount,error: e.toString()});await Future.delayed(Duration(seconds: 2));} else {rethrow;}}}if (response ! null (response.statusCode 200 || response.statusCode 206) response.data ! null) {final imageBytes Uint8List.fromList(response.data!);sendPort.send(imageBytes);} else {ImageLogger.logImageWarning(图片下载失败, {statusCode: response?.statusCode,message: response?.statusMessage});sendPort.send(null);}} catch (e) {ImageLogger.logImageError(图片下载异常, error: e);sendPort.send(null);}}/// 加载网络图片的Widget/// 功能提供图片加载的Widget封装/// 参数/// imageUrl: 图片URL/// width: 显示宽度/// height: 显示高度/// fit: 图片填充方式/// placeholder: 加载占位Widget/// errorWidget: 错误显示Widget/// cacheWidth: 缓存宽度/// cacheHeight: 缓存高度/// 工作流程/// 1. 检查URL是否有效/// 2. 使用FutureBuilder处理异步加载/// 3. 根据不同状态显示不同Widgetstatic Widget jiazaiTupian({required String? imageUrl,double? width,double? height,BoxFit fit BoxFit.cover,Widget? placeholder,Widget? errorWidget,int? cacheWidth,int? cacheHeight,}) {// 在实际使用时自动初始化_ensureInitialized();if (imageUrl null) {return const SizedBox.shrink();}return FutureBuilderUint8List?(future: _jiazaiTupianShuju(imageUrl),builder: (context, snapshot) {if (snapshot.connectionState ConnectionState.waiting) {return placeholder ?? SizedBox(width: width,height: height,child: const Center(child: CircularProgressIndicator()),);}if (snapshot.hasError || snapshot.data null) {if (EnvConfig.isDevelopment) {print(图片加载失败: ${snapshot.error});print(URL: $imageUrl);}return errorWidget ?? SizedBox(width: width,height: height,child: const Center(child: Column(mainAxisAlignment: MainAxisAlignment.center,children: [Icon(Icons.broken_image),Text(图片加载失败请稍后重试),],),),);}return Image.memory(snapshot.data!,key: ValueKey(imageUrl),width: width,height: height,fit: fit,cacheWidth: cacheWidth ?? (width?.toInt()),cacheHeight: cacheHeight ?? (height?.toInt()),gaplessPlayback: true,);},);}/// 加载图片数据/// 功能处理图片加载的核心逻辑/// 参数/// url: 图片URL/// 返回/// Uint8List?: 图片二进制数据/// 工作流程/// 1. 检查本地缓存/// 2. 如有缓存直接返回/// 3. 无缓存则下载并保存static FutureUint8List? _jiazaiTupianShuju(String url) async {// 在实际使用时自动初始化await _ensureInitialized();final huancun HuanCunGuanLi();// 先从缓存获取final cachedImage await huancun.huoquTupian(url);if (cachedImage ! null) {if (EnvConfig.isDevelopment) {print(从缓存加载图片: $url);}return cachedImage;}// 在独立isolate中加载图片final imageBytes await _loadInIsolate(url);if (imageBytes ! null) {// 保存到缓存await huancun.baocunTupian(url, imageBytes);}return imageBytes;} }
http://www.w-s-a.com/news/257931/

相关文章:

  • 东莞汽车总站停止营业crm管理系统在线使用
  • 深圳网站建设公司哪个网络优化是做什么的
  • 大连地区做网站自己怎么做电影网站
  • 成都APP,微网站开发手机要访问国外网站如何做
  • 网站app建设用discuz做的手机网站
  • vs 2008网站做安装包公众号登录超时
  • 银川做网站推广wordpress dux会员中心
  • 双辽做网站wordpress怎么写html代码
  • 建站公司哪家好 知道万维科技西安都有哪些公司
  • 设计网站官网入口佛山 品牌设计
  • 专用网站建设wordpress mega
  • 网站建设与优化推广方案内容网站整站下载带数据库后台的方法
  • 做网站PAAS系统外链是什么意思
  • 网页设计专业设计课程googleseo排名公司
  • 网站百度百科那些免费网站可以做国外贸易
  • 做视频的网站有哪些南京计算机培训机构哪个最好
  • ppt做视频 模板下载网站商业街网站建设方案
  • 佛山网站定制开发星光影视园网站建设案例
  • wordpress子站点商务网页设计与制作微课版答案
  • 山东省住房城乡和建设厅网站软件开发主要几个步骤
  • 可以接项目做的网站网站源码php
  • 杭州广众建设工程有限公司网站网页游戏人气排行榜
  • 上海网站开发建设最简单的网站代码
  • 东莞做网站建设免费网站建设案例
  • 莱州建设局网站wordpress的主题下载地址
  • 二级网站域名长沙企业关键词优化服务质量
  • 在家有电脑怎么做网站wordpress 入门主题
  • 什邡建设局网站sem推广是什么意思
  • 西安分类信息网站网站敏感关键词
  • 黑彩网站怎么做建设网站费用分析