Flutter Streambuilder不断重建

时间:2019-08-27 04:09:49

标签: firebase flutter google-cloud-firestore stream-builder

我有一个流生成器正在侦听Firestore,而且还可以。主要问题是streambuilder会不断重建(如果它不花我更多的钱,那就不用担心,但是如果这样做,那我就假设它确实有问题)。当第一次建立主页时,当我搜索到另一个页面时,它将再次构建,而当我弹出回到主页时,它将进行第三次重建。

代码:

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

2 个答案:

答案 0 :(得分:0)

每次在流中发生更改或调用build方法时,都会触发StreamBuilder。因此,要解决您的问题,请按如下所示更改代码。

class _RequestsListState extends State<RequestsList> with AutomaticKeepAliveClientMixin {
  final Map<String, List<Post>> posts = {};
  final List<String> postsUserIDs = [];
  StreamController<QuerySnapshot> _postStreamController = StreamController<QuerySnapshot>();

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

  _buildPostStreams();
  }

  _buildPostStreams() async{
     _postStreamController.add(APIs().posts.auPostsStream(cUserID: cUser.userID));
  }

  @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: _postStreamController.stream,
        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);
          }
        });
  }
}

我希望这会对您有所帮助。

答案 1 :(得分:0)

我知道这很晚了,但是使用您的init方法或使用provider在服务文件中调用提供程序将流移出构建上下文之外的方式是我进行设置的方式。让我知道你是否正确。