首页 > 解决方案 > 在 TabBarView 中加载 Firestore 数据

问题描述

我正在尝试创建一个用户界面,在主页中,用户有 3 个选项卡:组、事件、朋友。我StreamBuilder为每个选项卡构建了一个,但是当我在选项卡之间切换时,它会抛出一个错误,说该流已经被收听了。

我需要一种“重置”流的方法,因此当我切换回选项卡时它可以再次加载,即使我已经听过该流。

这是流媒体的代码 - 我目前只尝试访问事件数据,稍后每个选项卡都会有不同的流。

Stream<List<DocumentSnapshot>> _streamer() async* { //this is currently the only streamer - it only loads events.   
  var userEventsDocument = await Firestore.instance
      .collection('userEvents')
      .document(widget.uid)
      .get();

  var userEvents = List.from(userEventsDocument["eventlist"]);
  List<DocumentSnapshot> eventsSnapshot = List();

  for (var i = 0; i < userEvents.length; i++) {
    eventsSnapshot.add(await userEvents[i].get());
  }

  yield eventsSnapshot;
}

这就是我在 TabBarView 中使用流光的方式:

TabBarView(controller: _tabController, children: [
  StreamBuilder(
    stream: _streamer(),
    //Firestore.instance.collection("Events").snapshots(),
    builder: (BuildContext context, AsyncSnapshot<List<dynamic>> snapshot) {
      if (!snapshot.hasData) return const Text("Loading...");
      return SizedBox(
        height: MediaQuery.of(context).size.height -
          42 -
          MediaQuery.of(context).padding.bottom -
          AppBar().preferredSize.height -
          kToolbarHeight,
        child: Column(
          children: <Widget>[
            Expanded(
              child: Container(
                child: ListView.separated(
                  itemCount: snapshot.data.length,
                  itemBuilder: (context, index) =>
                      _buildListItem(context, snapshot.data[index]),
                  separatorBuilder: (context, index) {
                    return Divider();
                  },
                  shrinkWrap: true,
                ),
              ),
            )
          ],
        )
      );
    },
  ),
  StreamBuilder(
    stream: _streamer(),
    //Firestore.instance.collection("Events").snapshots(),
    builder: (BuildContext context,
        AsyncSnapshot<List<dynamic>> snapshot) {
      if (!snapshot.hasData) return const Text("Loading...");
      return SizedBox(
        height: MediaQuery.of(context).size.height -
            42 -
            MediaQuery.of(context).padding.bottom -
            AppBar().preferredSize.height -
            kToolbarHeight,
        child: Column(
          children: <Widget>[
            Expanded(
              child: Container(
                child: ListView.separated(
                  itemCount: snapshot.data.length,
                  itemBuilder: (context, index) =>
                      _buildListItem(context, snapshot.data[index]),
                  separatorBuilder: (context, index) {
                    return Divider();
                  },
                  shrinkWrap: true,
                ),
              ),
            )
          ],
        )
      );
    },
  ),
  StreamBuilder(
    stream: _streamer(),
    //Firestore.instance.collection("Events").snapshots(),
    builder: (BuildContext context,
        AsyncSnapshot<List<dynamic>> snapshot) {
      if (!snapshot.hasData) return const Text("Loading...");
      return SizedBox(
        height: MediaQuery.of(context).size.height -
            42 -
            MediaQuery.of(context).padding.bottom -
            AppBar().preferredSize.height -
            kToolbarHeight,
        child: Column(
          children: <Widget>[
            Expanded(
              child: Container(
                child: ListView.separated(
                  itemCount: snapshot.data.length,
                  itemBuilder: (context, index) =>
                      _buildListItem(context, snapshot.data[index]),
                  separatorBuilder: (context, index) {
                    return Divider();
                  },
                  shrinkWrap: true,
                ),
              ),
            )
          ],
        )
      );
    },
  ),
]),

标签: firebasefluttergoogle-cloud-firestoreflutter-layout

解决方案


我设法通过将小部件传递给 TabBarview 来做到这一点:

body: TabBarView(controller: _tabController, children:
              [TestScreen1(), TestScreen2(), TestScreen3()],
),

每个 TestScreens 都有一个构建器,该构建器使用自己的流构建器返回列表视图。


推荐阅读