Flutter ListView.builder滚动FPS过低(Android模拟器18.7)优化咨询
优化方案:解决ListView滚动时Map转换导致的性能问题
问题根源
你的代码中,itemBuilder会在ListView滚动的每一帧被频繁调用,而每次调用都执行controller.groupedList.keys.toList()和通过key查找Map的操作——这些重复计算会带来额外的性能开销,直接拉低帧率。
具体优化方案
1. 预缓存分组键与数据列表
将Map的keys转换和数据映射操作移出itemBuilder,只执行一次(或在数据更新时同步更新):
方案一:在Widget的State中缓存
late List<dynamic> _cachedKeys; @override void initState() { super.initState(); // 仅在初始化时计算一次keys列表 _cachedKeys = controller.groupedList.keys.toList(); } // 后续在itemBuilder中使用 ListView.builder( physics: BouncingScrollPhysics(), controller: scrollController, key: _animatedKey, scrollDirection: Axis.vertical, shrinkWrap: true, itemCount: controller.yearOld, itemBuilder: (context, index) { var thisYearList = controller.groupedList[_cachedKeys[index]]; return TimelineItemWidget( controller: controller, index: index, thisYearList: thisYearList); }, );
方案二:在Controller内部维护缓存结构
如果groupedList可能动态更新,建议在Controller中缓存转换后的列表,避免重复计算:
// 在你的Controller类中添加 List<dynamic>? _cachedKeys; List<List<Event>>? _cachedGroupedLists; List<dynamic> get cachedKeys { // 仅在keys为空或数据更新时重新计算 if (_cachedKeys == null || _cachedKeys!.length != groupedList.length) { _cachedKeys = groupedList.keys.toList(); } return _cachedKeys!; } List<List<Event>> get cachedGroupedLists { if (_cachedGroupedLists == null || _cachedGroupedLists!.length != groupedList.length) { _cachedGroupedLists = groupedList.values.toList(); } return _cachedGroupedLists!; } // 使用时直接调用缓存的列表 ListView.builder( // ...其他参数 itemCount: controller.cachedGroupedLists.length, itemBuilder: (context, index) { var thisYearList = controller.cachedGroupedLists[index]; return TimelineItemWidget( controller: controller, index: index, thisYearList: thisYearList); }, );
2. 移除不必要的shrinkWrap
shrinkWrap: true会强制ListView每次滚动时重新计算所有子项的总高度,这是性能杀手之一。如果你的布局允许,尽量移除该属性,让ListView填充父容器的可用空间。
3. 优化子Widget的重建
检查TimelineItemWidget是否可以使用const构造函数(如果传入的参数都是不可变类型),或者使用AutomaticKeepAliveClientMixin避免不可见的子项被频繁销毁重建。
内容的提问来源于stack exchange,提问作者matti peter
相关产品推荐
相关产品推荐

