如何捕获CachedNetworkImage加载404图片的Invalid image data异常
问题场景
开发图书列表功能时使用CachedNetworkImage组件,当传入的图片URL有误、资源不存在返回404状态时,Firebase Crashlytics会上报Invalid image data异常。但应用端实际已正常展示errorWidget中定义的浅黑色占位容器,该异常在调试模式下同样可以复现。目前由于该异常反复触发上报,Firebase持续发送告警邮件,需要实现该类异常的捕获拦截,避免无效上报。
当前实现代码如下:
CachedNetworkImage( width: 110.0, fit: BoxFit.cover, imageUrl: ebook.thumbnail, placeholder: (context, url) => Container(color: Colors.black12), errorWidget: (context, url, error) => Container(color: Colors.black12), )
原因说明
CachedNetworkImage内部在拿到接口返回的非图片格式数据(比如404页面的HTML内容)时,会先抛出解码异常,再触发errorWidget的渲染逻辑。组件本身没有默认吞掉这个异常,所以异常会透传到Flutter全局异常捕获链路,最终被Crashlytics采集上报。
解决方案
两种方案可以搭配使用,彻底拦截无效上报:
- 组件级消费异常:给
CachedNetworkImage配置errorListener回调,在回调中本地打印错误日志即可,不做向上抛出处理,从异常产生的源头做第一层拦截,修改后的代码如下:
CachedNetworkImage( width: 110.0, fit: BoxFit.cover, imageUrl: ebook.thumbnail, placeholder: (context, url) => Container(color: Colors.black12), errorWidget: (context, url, error) => Container(color: Colors.black12), errorListener: (error) { // 本地打印日志方便排查问题,不抛出异常 debugPrint('缩略图加载失败,地址:${ebook.thumbnail},错误:$error'); }, )
- 全局上报规则过滤:在Crashlytics的异常上报入口增加过滤逻辑,精准拦截漏网的同类异常,避免其他场景下的同类有效异常被误拦截,配置代码如下:
FlutterError.onError = (errorDetails) { final exceptionMsg = errorDetails.exception.toString(); final stackStr = errorDetails.stack.toString(); // 精准匹配:异常为无效图片数据,且异常来源是CachedNetworkImage组件 if (exceptionMsg.contains('Invalid image data') && stackStr.contains('CachedNetworkImage')) { debugPrint('忽略已知图片加载无效异常,不上报'); return; } // 其余异常正常走Crashlytics上报流程 FirebaseCrashlytics.instance.recordFlutterFatalError(errorDetails); };
注意:过滤条件必须同时匹配异常内容和堆栈中的组件标识,不要只靠
Invalid image data关键词拦截,否则会把其他场景(比如本地资源损坏、其他图片组件加载异常)的有效问题也过滤掉,影响线上问题排查。
内容的提问来源于stack exchange,提问作者Alex Aung
相关产品推荐
相关产品推荐

