Flutter 使用 Stream 检索 Firestore 集合

Posted

技术标签:

【中文标题】Flutter 使用 Stream 检索 Firestore 集合【英文标题】:Flutter Retrieving firestore collection using Stream 【发布时间】:2021-04-04 03:17:47 【问题描述】:

我正在尝试使用StreamBuilderfirestore 中检索整个集合,但我陷入了根据我的飞镖模型映射结果的过程中

这是飞镖模型thread.dart:

class Thread 
  final String threadTitle;
  final String threadContent;
  final String threadFlair;
  final String threadTimestamp;
  final List<String> threadLikedBy;
  final List<String> originalPoster;

  Thread(
    this.threadTitle,
    this.threadContent,
    this.threadTimestamp,
    this.threadFlair,
    this.threadLikedBy,
    this.originalPoster,
  );

  factory Thread.fromMap(Map<String, dynamic> map) => Thread(
    threadTitle: map["threadTitle"],
    threadContent: map["threadContent"],
    threadFlair: map["threadFlair"],
    threadTimestamp: map["threadTimestamp"],
    threadLikedBy: List<String>.from(map["threadLikedBy"].map((x) => x)),
    originalPoster: List<String>.from(map["originalPoster"].map((x) => x)),
  );

  Map<String, dynamic> toMap() => 
    "threadTitle": threadTitle,
    "threadContent": threadContent,
    "threadFlair": threadFlair,
    "threadTimestamp": threadTimestamp,
    "threadLikedBy": List<dynamic>.from(threadLikedBy.map((x) => x)),
    "originalPoster": List<dynamic>.from(originalPoster.map((x) => x)),
  ;

这是我在列表视图中显示结果的小部件:

class _ThreadsBodyState extends State<ThreadsBody> 
  final threads = _mThreadService.retriveData(path: "posts", builder: (data) => Thread.fromMap(data));
  @override
  Widget build(BuildContext context) 
    return Container(
      child: StreamBuilder<Object>(
        stream: threads,
        builder: (context, snapshot) 
          if (snapshot.hasData) 
            return ListView.builder(
              itemBuilder: (BuildContext context, int index) 
                Thread thrd = (snapshot.data as List)[index];
                return ThreadCard(thread: thrd,);
              ,
            );
            else return Text('no data');
      ),
    );
  

这里是 posts_service.dart 我有 Stream 功能的地方

//After restructuring my model and adding: 
//List<String> threadLikedBy; and List<String> originalPoster;
//this method works no more

Stream<List<T>> retrieveData<T>(
  @required String path,
  @required T builder(Map<String, dynamic> data),
) 
  final reference = firestoreInstance.collection(path);
  final snapshots = reference.snapshots();
  return snapshots.map((snapshot) => snapshot.docs.map((snapshot) => builder(snapshot.data())).toList());

似乎我弄乱了返回中的映射,但我无法完全弄清楚如何修复它。

【问题讨论】:

您有必要收听实时数据吗?您似乎正在处理新闻提要部分中的帖子,如果是这种情况,请告诉我,以便我提供解决方案/解决方法。 @ThorvaldOlavsen 是的,这就是我想要做的,但你不认为这些帖子应该是实时的吗? 您可以在用户滚动和刷新时加载数据,当用户位于列表的最顶部并下拉时。 @ThorvaldOlavsen 你能提供你的解决方案,以便我可以尝试实施它吗? 【参考方案1】:

在您的“posts_services.dart”中添加以下函数:

Future<QuerySnapshot> fetchThreads() async 
    return await firestoreInstance.collection('posts').get();

现在在您构建 ListView 的小部件中应该如下所示:

class _ThreadsBodyState extends State<ThreadsBody> 
  @override
  Widget build(BuildContext context) 
    return Container(
      child: FutureBuilder<QuerySnapshot>(
        future: youService.fetchThreads(),
        builder: (context, AsyncSnapshot<QuerySnapshot> snapshot) 
          if (snapshot.hasData) 
            return ListView.builder(
              itemCount: snapshot.data.size, //to retrieve the size
              itemBuilder: (BuildContext context, int index) 
                Thread thrd = Thread.fromMap(snapshot.data.docs[index].data());
                return ThreadCard(thread: thrd,);
              ,
            );
            else return Text('no data');
      ),
    );
  

【讨论】:

成功了!虽然我必须重新考虑是保持原样还是切换回实时

以上是关于Flutter 使用 Stream 检索 Firestore 集合的主要内容,如果未能解决你的问题,请参考以下文章

如何通过使用flutter bloc从fire存储中使用依赖注入来处理错误`The getter was called on null`

Flutter 使用 Stream 还是 Future?

从 Stream 检索快照时,Flutter/Firestore 返回类型 List<Review> 不是“Map<String, dynamic>”类型的子类型

将 Firebase 中的地图数据检索到 Flutter

Flutter:Fire Base 存储图像上传的后期初始化错误

从 Fire Storage 检索图像,但是如果图像不存在,则应用程序崩溃