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

Flutter从Firestore加载数据到列表时重复显示最后一条数据问题

嘿,这个问题我太熟了!一眼就看出问题出在哪——你在循环里一直复用同一个widget.challengesInfo对象,导致列表里所有元素都是同一个对象的引用,最后自然全显示成最后一次修改的数据啦。

具体来说,你每次循环只是修改widget.challengesInfo的属性,然后把它添加到allChallenges列表。但列表里存的是对象的引用,不是这个对象的副本。所以不管你加多少次,列表里的所有元素都指向同一个内存地址的对象,最后所有元素都会显示最后一次循环赋值的内容。

解决方法很简单:每次循环都新建一个AllChallengesStorage实例,而不是复用同一个。修改你的challengesToFeed方法:

Future<List<AllChallengesStorage>> challengesToFeed () async { 
  var queryResult = await Firestore.instance.collection("Users") 
    .where("total_challenges", isGreaterThanOrEqualTo: 1) 
    .getDocuments(); 
  // 每次请求前先清空列表,避免重复添加旧数据
  allChallenges.clear();
  if (queryResult.documents.isNotEmpty){
    for (int i=0; i < queryResult.documents.length; ++i){
      var userDoc = queryResult.documents[i];
      // 提前取出用户名,避免重复读取
      var userName = userDoc.data['username'];
      for (int j=0; j < userDoc.data['total_challenges']; ++j){
        // 关键:这里新建一个实例,而不是复用widget.challengesInfo
        var newChallenge = AllChallengesStorage();
        newChallenge.username = userName;
        newChallenge.name = userDoc.data['challenges'][j]['name'];
        newChallenge.description = userDoc.data['challenges'][j]['description'];
        newChallenge.duration = userDoc.data['challenges'][j]['duration'];
        allChallenges.add(newChallenge);
      }
    }
  }
  return allChallenges;
}

另外还有个小坑要提醒你:你现在在build方法里直接调用challengesToFeed(),这会导致每次组件重建(比如屏幕旋转、父组件刷新)时都重新发起Firestore请求,既浪费带宽又可能出现重复加载的问题。建议把这个Future存在State里,在initState中初始化:

class _FeedState extends State<Feed> { 
  List<AllChallengesStorage> allChallenges = []; 
  // 用late关键字声明,在initState里初始化
  late Future<List<AllChallengesStorage>> _challengesFuture;

  @override
  void initState() {
    super.initState();
    // 只在组件初始化时请求一次数据
    _challengesFuture = challengesToFeed();
  }

  @override 
  Widget build(BuildContext context) { 
    return Scaffold( 
      body: FutureBuilder<List<AllChallengesStorage>>( 
        future: _challengesFuture, // 使用提前初始化的Future
        builder: (BuildContext context, AsyncSnapshot snapshot) { 
          if (!snapshot.hasData) return Center(child: Text("Loading...")); 
          return ListView.builder( 
            itemCount: snapshot.data.length, 
            itemBuilder: (BuildContext context, int index) { 
              return _cardBuilder(context, snapshot, index); 
            }, 
          ); 
        }, 
      ), 
    ); 
  }
}

这样修改后,每个列表项都会对应独立的AllChallengesStorage实例,显示的内容就会正确啦!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 07:35:21