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

Flutter热重载或返回页面时ListView列表重复增长问题求解

问题根源

列表重复累加是两个写法错误导致的:

  • courses被声明为Future<List<String>>类型,你没有在方法内初始化新的列表实例,每次调用getFolders()都会往已存在的旧列表对象上追加数据,页面返回、热重载触发重建时重复执行拉取逻辑,数据自然会越积越多。你猜测的点是对的:不能直接对Future类型对象调用add方法,Future是异步结果的封装,不是实际的列表实例。
  • FutureBuilder的渲染逻辑错误:你直接对courses这个Future对象取length、按下标取值,拿不到实际的列表数据,渲染逻辑本身就不成立。
修复方案
  1. 把courses的初始化放到initState生命周期中,不要在build方法里赋值,避免每次重建都重复触发拉取
  2. 改写getFolders方法:方法内部新建临时空列表承载拉取到的文件夹名称,不要操作外部的Future对象,拉取完成后直接返回这个临时列表
  3. 修正FutureBuilder逻辑:通过snapshot.data获取异步返回的实际列表,所有列表渲染逻辑都基于这个快照返回的数据实现,不要直接操作外部的Future变量
修复后代码参考
class _SemesterState extends State<Semester> {
  late Future<List<String>> courses;

  @override
  void initState() {
    super.initState();
    courses = getFolders();
  }

  Future<List<String>> getFolders() async {
    // 每次拉取新建空列表,从根源避免数据累加
    List<String> folderList = [];
    final storageRef = FirebaseStorage.instance.ref().child(widget.value);
    final listResult = await storageRef.listAll();
    for (var prefix in listResult.prefixes) {
      folderList.add(prefix.name);
    }
    return folderList;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.white,
      appBar: AppBar(
        title: const Text("Semester", style: kTitleStyle),
        backgroundColor: Colors.white,
      ),
      body: FutureBuilder<List<String>>(
        future: courses,
        builder: (context, snapshot) {
          if (snapshot.connectionState == ConnectionState.waiting) {
            return const Center(
              child: spinkitLines,
            );
          }
          if (snapshot.hasError) {
            return Center(child: Text('加载失败: ${snapshot.error}'));
          }
          // 从快照中拿到实际渲染用的列表
          final courseList = snapshot.data ?? [];
          return Column(
            children: [
              const SizedBox(height: 20.0),
              const Center(
                child: Text(
                  'Tap to choose course',
                  style: kPlaceholderStyle,
                ),
              ),
              const SizedBox(height: 30.0),
              Expanded(
                child: ListView.builder(
                    itemCount: courseList.length,
                    itemBuilder: (context, index) {
                      return Padding(
                        padding: const EdgeInsets.all(8.0),
                        child: GestureDetector(
                          onTap: () {
                            // 点击业务逻辑
                          },
                          child: Container(
                            height: 80,
                            decoration: const BoxDecoration(
                              // 原有装饰配置
                            ),
                            child: Center(
                              child: Padding(
                                padding: const EdgeInsets.all(5.0),
                                child: Text(
                                  courseList[index],
                                  style: kCardTitleStyle,
                                ),
                              ),
                            ),
                          ),
                        ),
                      );
                    }),
              )
            ],
          );
        },
      ),
    );
  }
}

如果后续需要手动刷新列表,单独实现刷新方法,方法内重新调用getFolders()给courses赋值后调用setState即可,不要修改initState中的初始化逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 20:18:18