使用SliverList时如何将图片保留在内存中?
问题描述
滚动包含图片的长SliverList时,图片滚出屏幕后会消失,回滚需重新加载,如何将图片缓存到内存实现立即显示?
现有代码
SliverList.builder( itemCount: meals.length, addAutomaticKeepAlives: true, itemBuilder: (context, index) { return Padding( padding: const EdgeInsets.only(bottom: 8.0), child: _mealLog(meals[index]), ); }, ) Widget _mealLog(Meal meal) { return Column(children: [Text(meal.label), CachedNetworkImage( imageUrl: meal.imageUrl, width: 60, height: 60, fit: BoxFit.cover, placeholder: (context, url) => placeholder(), errorWidget: (context, error, stackTrace) { return placeholder(); }, ), ]); }
解决方法
1. 自定义CachedNetworkImage内存缓存配置
cached_network_image底层依赖flutter_cache_manager,可以自定义缓存管理器来控制内存缓存的数量和有效期:
// 初始化自定义缓存管理器 final mealImageCacheManager = CacheManager( Config( 'meal_image_cache', stalePeriod: const Duration(days: 7), // 缓存有效期7天 maxNrOfCacheObjects: 100, // 内存中最多缓存100张图片 ), ); // 在CachedNetworkImage中使用该管理器 CachedNetworkImage( imageUrl: meal.imageUrl, cacheManager: mealImageCacheManager, width: 60, height: 60, fit: BoxFit.cover, placeholder: (context, url) => placeholder(), errorWidget: (context, error, stackTrace) => placeholder(), )
2. 确保AutomaticKeepAlive生效
虽然设置了addAutomaticKeepAlives: true,但无状态Widget无法保留状态,需将_mealLog改为带状态的Widget并混入AutomaticKeepAliveClientMixin:
class MealLogItem extends StatefulWidget { final Meal meal; const MealLogItem({required this.meal, Key? key}) : super(key: key); @override State<MealLogItem> createState() => _MealLogItemState(); } class _MealLogItemState extends State<MealLogItem> with AutomaticKeepAliveClientMixin { @override bool get wantKeepAlive => true; // 开启状态保留 @override Widget build(BuildContext context) { super.build(context); // 必须调用super.build return Column(children: [ Text(widget.meal.label), CachedNetworkImage( imageUrl: widget.meal.imageUrl, width: 60, height: 60, fit: BoxFit.cover, placeholder: (context, url) => placeholder(), errorWidget: (context, error, stackTrace) => placeholder(), ), ]); } } // 在itemBuilder中替换为该组件 return Padding( padding: const EdgeInsets.only(bottom: 8.0), child: MealLogItem(meal: meals[index]), );
3. 扩大列表缓存区域
通过cacheExtent参数让列表提前加载并保留滚出屏幕的Widget,避免立即销毁:
SliverList.builder( itemCount: meals.length, addAutomaticKeepAlives: true, cacheExtent: 500.0, // 单位:逻辑像素,可根据实际列表项高度调整 itemBuilder: (context, index) { return Padding( padding: const EdgeInsets.only(bottom: 8.0), child: MealLogItem(meal: meals[index]), ); }, )
内容的提问来源于stack exchange,提问作者opsb
相关产品推荐
相关产品推荐

