Flutter代码陷入无限循环,无法正常渲染2个CategoryViewer
问题根源与修复方案
核心问题拆解
- 方法循环调用导致列表无限膨胀:
getHighProteinDrinks()内部调用了getHighFiberDrinks(),再加上initState里同时触发两个方法,drinkCategories会被反复添加重复组件。 - GridView无终止构建条件:
GridView.builder没设置itemCount,Flutter会持续调用itemBuilder;更关键的是,每次构建都执行getHighFiberDrinks(),这个方法又会往drinkCategories加元素,触发组件重建,形成死循环。 - 冗余遍历完全无效:两个
getXXXDrinks里的for循环纯属鸡肋,ListView.builder只需要一次初始化就能根据数据源长度生成列表,没必要遍历每个元素重复赋值。
修复后的完整代码
class CategoriesScreenCopy extends ConsumerStatefulWidget { const CategoriesScreenCopy({super.key}); @override ConsumerState<CategoriesScreenCopy> createState() => _CategoriesScreenState(); } class _CategoriesScreenState extends ConsumerState<CategoriesScreenCopy> { List<Widget> drinkCategories = []; Widget getHighProteinDrinks() { return ListView.builder( scrollDirection: Axis.horizontal, itemCount: highProteinDrinks.length, itemBuilder: (ctx, index) => DrinkItem( drink: highProteinDrinks[index], ), ); } Widget getHighFiberDrinks() { return ListView.builder( scrollDirection: Axis.horizontal, itemCount: highFiberDrinks.length, itemBuilder: (ctx, index) => DrinkItem( drink: highFiberDrinks[index], ), ); } @override void initState() { super.initState(); // 直接将两个分类组件添加到列表 drinkCategories.add(getHighProteinDrinks()); drinkCategories.add(getHighFiberDrinks()); } @override Widget build(BuildContext context) { return Scaffold( body: GridView.builder( gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 1, childAspectRatio: 3 / 3, crossAxisSpacing: 20, mainAxisSpacing: 8, ), // 绑定列表长度,限制GridView构建次数 itemCount: drinkCategories.length, itemBuilder: (context, index) => CategoryViewer( categoryDrinkList: drinkCategories[index], // 根据索引匹配对应分类名称 categoryDrinkName: index == 0 ? 'High-Protein Drinks' : 'High-Fiber Drinks', ), ), ); } }
关键修复说明
- 切断循环调用链:
getHighProteinDrinks()不再嵌套调用getHighFiberDrinks(),改为在initState里分别调用两个方法,将结果一次性加入drinkCategories。 - 给GridView加终止条件:设置
itemCount为drinkCategories.length,让GridView只构建你需要的2个组件。 - 删掉无用的for循环:直接返回
ListView.builder即可,它本身就能处理列表渲染逻辑。 - 匹配正确的分类数据与名称:通过索引从
drinkCategories取对应组件,并设置对应的分类名称,避免重复显示同一内容。
内容的提问来源于stack exchange,提问作者user14367514
相关产品推荐
相关产品推荐

