Flutter弱网环境下DefaultCacheManager报错如何处理
问题修复方案
错误根源
你遇到的ScaffoldFeatureController异常是代码逻辑错误直接导致的:
- 你在
showSnackBar的参数位置、timeout回调中错误使用了throw关键字,把showSnackBar方法返回的ScaffoldFeatureController实例作为异常抛出,直接触发了报错 getSingleFile的onError、timeout回调要求返回File类型的有效值,你当前没有返回对应类型值,后续赋值给VideoPlayerController.file时也会触发类型异常- 异步操作过程中可能出现页面销毁、context失效的情况,直接使用
_buildContext!强转也会引发崩溃
修正后的实现代码
Future<void> _downloadAndCache() async { // 先校验网络状态和context有效性 if (_connectionStatusMobile != "ConnectivityResult.mobile" || _buildContext?.mounted != true) { return; } File? file; try { file = await DefaultCacheManager() .getSingleFile(url) .timeout(const Duration(minutes: 3)); } catch (error, stackTrace) { await DefaultCacheManager().emptyCache(); if(mounted) { setState(() { isDownloadedError = true; }); } // 上下文有效才展示SnackBar if (_buildContext?.mounted == true) { ScaffoldMessenger.of(_buildContext!).showSnackBar( SnackBar( content: Text(error is TimeoutException ? "İndirme Tamamlanamadı." : error.toString()), duration: const Duration(seconds: 3), ), ); } // 异常直接终止后续逻辑 return; } // 确认文件存在再初始化播放器 if (file != null && await file.exists()) { _videoController = VideoPlayerController.file(file) ..initialize().then((_) { if (mounted) { setState(() { isDownloaded = true; _videoController!.play(); _videoController!.setLooping(true); }); } }).onError((error, stackTrace) { // 增加播放器初始化异常处理 if(mounted) { setState(() { isDownloadedError = true; }); } if (_buildContext?.mounted == true) { ScaffoldMessenger.of(_buildContext!).showSnackBar( const SnackBar( content: Text("视频加载失败,请稍后重试"), duration: Duration(seconds: 3), ), ); } }); } }
额外优化建议
- 弱网场景下可以给
getSingleFile增加重试逻辑,提升下载成功率 - 可以提前校验下载文件的大小、完整性,避免下载到损坏的视频文件
- 下载过程中增加loading提示,避免用户重复触发下载操作
内容的提问来源于stack exchange,提问作者mehmet akif sayrım
相关产品推荐
相关产品推荐

