【问题标题】:StreamController with Firestore带有 Firestore 的 StreamController
【发布时间】:2019-02-04 23:48:32
【问题描述】:

我想使用StreamController 来控制从Firestore 的集合中获取数据的StreamBuilder。这将使我能够使用RefereshIndicator,这样当我下拉列表时,它会刷新/获取更多数据(如果有的话)。

我使用了article 中的大部分信息。我当前的代码如下

    class _Lists extends State<List> {
      StreamController _controller;
      final GlobalKey<ScaffoldState> scaffoldKey = new GlobalKey<ScaffoldState>();

        @override
         void initState() {
        _controller = new StreamController();
         loadPosts();         
        super.initState();
        }

       Future fetchPost() async {
       return await . 
       Firestore.instance.collection(_locationState).snapshots();
        }

      Future<Null> _handleRefresh() async {
      count++;
      print(count);
       fetchPost().then((res) async {
       _controller.add(res);
       showSnack();
        return null;
      });
     }

      showSnack() {
      return scaffoldKey.currentState.showSnackBar(
      SnackBar(
      content: Text('New content loaded'),
      ),
       );  
     }

      loadPosts() async {
      fetchPost().then((res) async {
       print(res.document);
       _controller.add(res);
      return res;
      });
      }


       @override
   Widget build(BuildContext context) {
   final topBar = AppBar(Title("List"));
   bottom: TabBar(
    indicatorColor: Colors.blueAccent,
    indicatorWeight: 3.0,
    //indicatorSize: 2.0,
    indicatorPadding:
        const EdgeInsets.only(bottom: 10.0, left: 47.0, right: 
    47.0),
    tabs: [
      Tab(
        child: Image(
          image: AssetImage("MyImage1"),
          width: 65.0,
          height: 65.0,
        ),
      ),
      Tab(
        child: Image(
          image: AssetImage("Image2"),
          width: 90.0,
          height: 90.0,
        ),
      ),
    ],
  ),

return DefaultTabController(
    length: 2,
    child: Scaffold(
        key: scaffoldKey,
        appBar: topBar,
        body: StreamBuilder(
            stream: _controller.stream,
            builder: (BuildContext context, AsyncSnapshot snapshot) {
              if (snapshot.hasError) {
                return Text(snapshot.error);
              }
              if (snapshot.connectionState == ConnectionState.active) {
                List aList = new List();
                aList.clear();
                for (DocumentSnapshot _doc in snapshot.data.documents) {
                  Model _add = new Model.from(_doc);
                  aList.add(_add);
                }
                return TabBarView(
                  children: <Widget>[
                    RefreshIndicator(
                      onRefresh: _handleRefresh,
                      child: ListView.builder(
                        itemCount: aList.length,
                        itemBuilder: (context, index) {
                          return Card(aList[index]);
                        },
                      ),
                    ),
                    Icon(Icons.directions_transit),
                  ],
                );
              } else {
                return Container(
                    child: Center(child: CircularProgressIndicator()));
              }
            })));
 }
}
}

我遇到的问题是我不断收到错误

    flutter: ══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY 
╞═══════════════════════════════════════════════════════════
flutter: The following NoSuchMethodError was thrown building 
StreamBuilder<dynamic>(dirty, state:
flutter: _StreamBuilderBaseState<dynamic, 
AsyncSnapshot<dynamic>>#53c04):
flutter: Class '_BroadcastStream<QuerySnapshot>' has no instance getter 'documents'.
flutter: Receiver: Instance of '_BroadcastStream<QuerySnapshot>'
flutter: Tried calling: documents

关于如何将StreamController 与来自Firestore 的数据一起使用的任何想法?

【问题讨论】:

    标签: firebase dart flutter google-cloud-firestore


    【解决方案1】:

    密切关注 IDE 中的返回类型可能有助于避免很多类似的令人困惑的问题。不幸的是,该博客没有在 then 语句中指出 API 调用、StreamController 或“res”的任何类型。声明这些类型将有助于显示您正在使用的内容(至少它在 Android Studio 中对我有用)。例如,在带有来自 Firestore 的流的 StreamBuilder 中,我使用 AsyncSnapshot&lt;QuerySnapshot&gt; snapshot 而不仅仅是 AsyncSnapshot。这允许 Android Studio 中的工具告诉我 snapshot.data.documents 是来自 QuerySnapshot 类的映射。如果我不添加额外的类型,我看不到。

    这里是一个监听来自Firestore Dart package的流的例子。

    //Performing a query:
    
    Firestore.instance
        .collection('talks')
        .where("topic", isEqualTo: "flutter")
        .snapshots()
        .listen((data: QuerySnapshot) =>
            // do stuff here
        );
    

    由于您使用的是 async/await 样式(也非常好),因此您将获得与 .listen((data) =&gt; 相同的结果。我们可以按照文档/类来查看返回的类型。

    Firestore.instance.collection(&lt;whatever&gt;).snapshots() 将返回 Stream&lt;QuerySnapshot&gt;, 所以我们知道 await Firestore.instance.collection(&lt;whatever&gt;).snapshots() 将返回 QuerySnapshot.

    进一步研究该类,我们发现它有一个名为 documents 的属性。

      /// Gets a list of all the documents included in this snapshot
      final List<DocumentSnapshot> documents;
    

    这最终为我们提供了 DocumentSnapshots,您必须从中提取 data 属性。

    因此,在您的情况下,我相信 res 类型为 QuerySnapshot 将有助于向您展示要放入流中的数据,此时可以通过多种方式完成。 List&lt;DocumentSnapshot&gt; 看起来像你想要的,但你可以更进一步到从 DocumentSnapshot data 属性构建的 List&lt;YourClass&gt;。这样,您就可以说出您的 StreamController 将返回什么数据类型,从而使构建器的 AsyncSnapshot&lt;your stream type&gt; 更易于使用。

    我不确定您使用的是什么开发工具,但如果您不熟悉,您可以执行以下操作:按下/按住(命令或 ctrl),将鼠标悬停在类型/类/功能/ var 你想看,左键单击,你应该被带到源文件/声明(我觉得这超级方便)。

    【讨论】:

      猜你喜欢
      • 2019-07-23
      • 2019-04-20
      • 2020-03-13
      • 1970-01-01
      • 2021-03-03
      • 1970-01-01
      • 2021-10-10
      • 2019-03-29
      • 2019-06-18
      相关资源
      最近更新 更多