You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter GridView未显示问题排查:按大洲动态展示国家的复用Widget故障

动态按大洲展示国家的GridView问题排查与优化

问题描述

尝试以动态方式按大洲展示国家,让Widget可复用至其他大洲场景,但GridView完全无法正常工作,页面与调试控制台均无内容显示。需定位问题并解决,同时寻求更优实现方式。

预期效果:
预期展示效果

相关代码

ShowByContinent组件代码

class ShowByContinent extends ConsumerStatefulWidget {
  final String continent;

  ShowByContinent({
    required this.continent,
    super.key,
  });

  @override
  ConsumerState<ConsumerStatefulWidget> createState() =>
      _ShowByContinentState();
}

class _ShowByContinentState extends ConsumerState<ShowByContinent> {
  @override
  Widget build(BuildContext context) {
    List continentCountry = [];
    showByContinent() {
      countries_info.forEach((key, value) {
        if (value["continent"] == widget.continent) {
          continentCountry = key.split(",");
        }
      });
    }

    showByContinent();
    return Expanded(
      child: GridView.builder(
          itemCount: continentCountry.length,
          gridDelegate:
              SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3),
          itemBuilder: (BuildContext context, int index) {
            return Container(
              child: continentCountry[index],
              height: 100,
              width: 100,
            );
          }),
    );
  }
}

父Widget代码

class _ResultsState extends ConsumerState<Results> {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Center(
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.center,
            children: [
              Text("BRAVO You found : "),

              Text(
                "${countryName.length}/${countries_info.length} country",
                style: const TextStyle(color: Colors.black),
              ),
              ProgessBar(
                  totalCounrty: countries_info.length,
                  guessedCountry: countryName.length),
              Column(
// Level
                children: [
                  Text("Dificulty:"),
                  Row(
                    mainAxisAlignment: MainAxisAlignment.center,
                    crossAxisAlignment: CrossAxisAlignment.center,
                    children: [
                      Icon(Icons.star),
                      Icon(Icons.star_border_outlined),
                      Icon(Icons.star_border_outlined),
                      Icon(Icons.star_border_outlined)
                    ],
                  ),
                  Text("My score : ${countryName.length} pts"),
                  Text("My best score : $bestScore pts"),
                  Text("+ $difScore"),
                  ElevatedButton(onPressed: () {}, child: Text("Play Again?")),
                ],
              ),
              ShowByContinent(
                continent: "Asia",
              )
            ],
          ),
        ),
      ),
    );
  }
}

问题排查

  1. 列表数据逻辑错误:showByContinent方法中,每次匹配到对应大洲的条目时,直接用continentCountry = key.split(",")覆盖整个列表,而非累加元素。这会导致最终仅保留最后一个匹配项的拆分结果,若没有匹配项则列表为空。
  2. Widget类型错误:continentCountry[index]是字符串类型,但Container的child必须是Widget,直接传入字符串会导致渲染失败(部分场景下控制台可能未输出错误)。
  3. 数据加载时机不合理:在build方法内每次都重新遍历数据,既浪费性能,也无法保证数据更新时UI同步。

修复与优化方案

修复后的ShowByContinent组件代码

class ShowByContinent extends ConsumerStatefulWidget {
  final String continent;

  const ShowByContinent({
    required this.continent,
    super.key,
  });

  @override
  ConsumerState<ShowByContinent> createState() => _ShowByContinentState();
}

class _ShowByContinentState extends ConsumerState<ShowByContinent> {
  List<String> continentCountry = [];

  @override
  void initState() {
    super.initState();
    _loadCountriesByContinent();
  }

  @override
  void didUpdateWidget(covariant ShowByContinent oldWidget) {
    super.didUpdateWidget(oldWidget);
    // 大洲参数变化时重新加载数据
    if (oldWidget.continent != widget.continent) {
      _loadCountriesByContinent();
    }
  }

  void _loadCountriesByContinent() {
    continentCountry.clear();
    countries_info.forEach((key, value) {
      if (value["continent"] == widget.continent) {
        // 累加匹配到的所有国家
        continentCountry.addAll(key.split(","));
      }
    });
    setState(() {});
  }

  @override
  Widget build(BuildContext context) {
    return Expanded(
      child: GridView.builder(
        padding: const EdgeInsets.all(16),
        itemCount: continentCountry.length,
        gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
          crossAxisCount: 3,
          crossAxisSpacing: 12,
          mainAxisSpacing: 12,
        ),
        itemBuilder: (context, index) {
          return Container(
            alignment: Alignment.center,
            decoration: BoxDecoration(
              border: Border.all(color: Colors.grey.shade300),
              borderRadius: BorderRadius.circular(8),
              color: Colors.white,
            ),
            // 用Text组件包裹字符串,确保正确渲染
            child: Text(
              continentCountry[index],
              textAlign: TextAlign.center,
              style: const TextStyle(fontSize: 14),
            ),
          );
        },
      ),
    );
  }
}

优化说明

  • 数据加载优化:将数据加载逻辑移至initState和didUpdateWidget,避免build方法重复遍历数据;使用addAll替代直接赋值,确保所有匹配的国家都被加入列表。
  • 类型安全:给continentCountry指定List<String>类型,避免动态类型带来的潜在问题。
  • UI优化:添加内边距、间距、边框和背景色,让展示效果更贴近预期;用Text组件正确渲染字符串内容。
  • 状态同步:数据更新时调用setState触发UI重建,保证数据与视图同步。

内容的提问来源于stack exchange,提问作者Coca95

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 21:32:40