Flutter Streambuilder 不断重建

Posted

技术标签:

【中文标题】Flutter Streambuilder 不断重建【英文标题】:Flutter Streambuilder rebuilds constantly 【发布时间】:2019-12-31 05:10:51 【问题描述】:

我有一个监听 Firestore 的流生成器​​,它还挺有效的。主要问题是流构建器不断重建(如果它不花费我额外的阅读费用,那么不用担心,但如果确实如此,那么这是一个问题,我假设它确实如此)。当主页面第一次构建时,当我转到另一个页面时它会再次构建,当我弹回主页面时它会第三次构建。

代码:

class _RequestsListState extends State<RequestsList> with AutomaticKeepAliveClientMixin 
  final Map<String, List<Post>> posts = ;
  final List<String> postsUserIDs = [];

  @override
  bool get wantKeepAlive => true;

  @override
  Widget build(BuildContext context) 
    super.build(context);

    print('RequestsList');
    User cUser = InheritedUser.of(context).user;

    return StreamBuilder<List<Post>>(
        initialData: cUser.posts,
        stream: APIs().posts.auPostsStream(cUserID: cUser.userID),
        builder: (context, snap) 
          if (snap.hasError) 
            print('AUPostsList.dart StreamBuilder Error: $snap.error');
            return null;
           else 

            print('POSTS LENGTH');
            print(snap.connectionState);
            print(cUser.posts.length);

            this.posts.clear();
            this.postsUserIDs.clear();

            snap.data.forEach((post) 
              if (this.posts[post.user.documentID] == null) 
                this.posts[post.user.documentID] = [post];
               else 
                this.posts[post.user.documentID].add(post);
              

              if (!this.postsUserIDs.contains(post.user.documentID)) 
                this.postsUserIDs.add(post.user.documentID);
              
            );

            return ListView.separated(
                controller: widget.scrollController,
                physics: BouncingScrollPhysics(),
                shrinkWrap: true,
                padding: EdgeInsets.only(top: 0.0),
                itemBuilder: (context, index) => RequestItem(posts: this.posts[this.postsUserIDs[index]]),
                separatorBuilder: (context, index) => Container(),
                itemCount: this.postsUserIDs.length);
          
        );
  

其次,当我转到第二页时,数组被清空了。我没有在任何地方清除它,所以我不确定为什么在点击一个项目后它会清空数组......

日志:

Reloaded 0 of 773 
libraries in 169ms.
flutter: ChatsList
flutter: RequestsList
flutter: POSTS LENGTH
flutter: ConnectionState.waiting
flutter: 1
flutter: RequestsList
flutter: POSTS LENGTH
flutter: ConnectionState.waiting
flutter: 0
flutter: ChatsList
flutter: RequestsList
flutter: POSTS LENGTH
flutter: ConnectionState.waiting
flutter: 0
flutter: ChatsList

【问题讨论】:

你能解决这个问题吗? 【参考方案1】:

我知道这已经很晚了,但是使用您的 init 方法或使用提供程序在服务文件中进行调用将流移到构建上下文之外是我进行设置的方式。如果你来对了,请告诉我。

【讨论】:

对我来说,流中不同的方法有助于避免不必要的重建。【参考方案2】:

您的假设是正确的...因为 StreamBuilder 在您的 Build 方法中,它会在每次实例化 Widget 时从 Firestore 读取。

所以在这种情况下,使用AutomaticKeepAliveClientMixin 来保持 Widget 状态并没有帮助。

Wesley 是对的——你应该使用 init 方法来创建你的流——这样流只会被调用一次。查看this answer for more info

【讨论】:

以上是关于Flutter Streambuilder 不断重建的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Flutter listview streambuilder 中停止自动滚动?

FirebaseStorage + Flutter,streamBuilder?

来自一个 StreamBuilder 的 Flutter 快照显示在另一个 StreamBuilder 中

Flutter:Streambuilder - 关闭流

Flutter:StreamBuilder 快照——无数据

Flutter Streambuilder 正在复制项目