如何延迟ListView或Image.network请求以避免出现statusCode: 444错误
问题原因
你之前的实现中,Future.delayed仅延迟了整个ListView的初始化时机,等延迟结束后ListView会一次性渲染当前可视区域+预加载区域的所有列表项,对应图片会同时批量发起请求,自然无法达到间隔请求的效果。
返回444状态码是目标站点的服务端触发了高频访问限流,短时间内批量请求被服务端直接拦截断开连接。
可行解决方案
方案1:缩小ListView预加载范围(快速优化)
禁用或缩小ListView的预加载区域,减少同时触发的图片请求数量:
FutureBuilder( future: Future.delayed(Duration(milliseconds: 500)), builder:(c,s)=> ListView.builder( cacheExtent: 0, // 完全禁用预加载,仅渲染当前屏幕可见的列表项 itemCount: 50, itemBuilder(context, index){ return Card( child: Row( children: [ CachedNetworkImage( imageUrl: imagesLink[index], placeholder: (context, url) => CircularProgressIndicator(), errorWidget: (context,url,error) => new Icon(Icons.error), ), ] ), ); } ) )
方案2:阶梯延迟发起请求(满足延迟需求)
将延迟逻辑加在每个图片的加载流程中,保证相邻图片的请求间隔:
ListView.builder( cacheExtent: 0, itemCount: 50, itemBuilder: (context, index) { return Card( child: Row( children: [ FutureBuilder( // 每个图片比前一个晚200ms发起请求,间隔可自行调整 future: Future.delayed(Duration(milliseconds: index * 200)), builder: (context, snapshot) { if (snapshot.connectionState != ConnectionState.done) { return CircularProgressIndicator(); } return CachedNetworkImage( imageUrl: imagesLink[index], placeholder: (context, url) => CircularProgressIndicator(), errorWidget: (context,url,error) => Icon(Icons.error), ); }, ) ] ), ); } )
方案3:限制全局下载并发数(更稳定,适配滚动场景)
阶梯延迟在用户快速滚动时仍可能触发批量请求,更稳妥的方案是自定义CachedNetworkImage依赖的缓存管理器,从根源限制同时发起的请求数量:
- 先创建自定义缓存管理器,调整最大并发下载数:
import 'package:flutter_cache_manager/flutter_cache_manager.dart'; class CustomCacheManager extends CacheManager with ImageCacheManager { static const key = 'customImageCache'; static final CustomCacheManager _instance = CustomCacheManager._(); factory CustomCacheManager() => _instance; CustomCacheManager._() : super(Config( key, maxNrOfCacheObjects: 200, // 最大同时下载数设为2,可根据服务端限流规则调整 maxConcurrentDownloads: 2, )); }
- 在CachedNetworkImage中指定使用自定义缓存管理器:
CachedNetworkImage( imageUrl: imagesLink[index], cacheManager: CustomCacheManager(), placeholder: (context, url) => CircularProgressIndicator(), errorWidget: (context,url,error) => Icon(Icons.error), )
内容的提问来源于stack exchange,提问作者Ktrel
相关产品推荐
相关产品推荐

