【问题标题】:Flutter-Firestore transform Stream<List<DocumentSnapshot<Map<String, dynamic>>>> into List<MyClass>Flutter-Firestore 将 Stream<List<DocumentSnapshot<Map<String, dynamic>>>> 转换为 List<MyClass>
【发布时间】:2021-11-11 12:12:05
【问题描述】:

我创建了一个函数,我想返回数据库中半径内的所有位置。这就是我使用 GeoFlutterFire 的原因。我的问题是我不知道如何将 Stream>>> 转换为我的 Class 类型的 List


import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:geoflutterfire/geoflutterfire.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_storage/firebase_storage.dart';
import 'package:uerto/models/index.dart';

class SearchApi {
  const SearchApi({required FirebaseAuth auth, required FirebaseFirestore firestore, required FirebaseStorage storage, required Geoflutterfire geo})
      : _auth = auth,
        _firestore = firestore,
        _storage = storage,
        _geo = geo;

  final FirebaseAuth _auth;
  final FirebaseFirestore _firestore;
  final FirebaseStorage _storage;
  final Geoflutterfire _geo;

  Future<List<AppClient>> getClientList() async{

    final List<AppClient> newResult = <AppClient>[];

    final GeoFirePoint center = _geo.point(latitude: 44.414445, longitude: 26.01135501);

    final CollectionReference<Map<String, dynamic>> collectionReference = _firestore.collection('clients/London/Beauty');

    final double radius = 5000;
    const String field = 'point';

    final  Stream<List<DocumentSnapshot<Map<String, dynamic>>>> stream = _geo.collection(collectionRef: collectionReference).within(center: center, radius: radius, field: field);

    ///something to transform Stream<List<DocumentSnapshot<Map<String, dynamic>>>> stream into List<AppClient> result;

    newResult.addAll(result);

    return newResult;

  }
}

【问题讨论】:

  • 也许只需访问流中的片刻即可一次获取一个列表。因为您的流不是列表。如果您不需要将流留在一个对象中,您可以将流分块为更小的列表记录。
  • 参见Stream.first 属性例如 - 文档说:“此流的第一个元素。收到第一个元素后停止侦听此流。”

标签: firebase flutter dart google-cloud-firestore geohashing


【解决方案1】:
stream.listen((List<DocumentSnapshot> documentList) {
  // this function would be called when ever documentList changes.
  // So, it might be called even after your getClientsList() is completed.
  List<Map<String, dynamic>> newResult = documentList.map((e) => e.data()).toList();
});

由于getClientsList 返回一个未来,您可能希望将流转换为一个未来。在这种情况下,您可以使用它。

List<Map<String, dynamic>> newResult = (await stream.first).map((e) => e.data()).toList();

或者,您可以使用流构建器收听流。像这样。

StreamBuilder<DocumentSnapshot>(
  stream: _geo.collection(collectionRef: collectionReference)
      .within(center: center, radius: radius, field: field),
  builder:
      (BuildContext context, AsyncSnapshot<DocumentSnapshot> snapshot) {
    if (snapshot.hasError) return Text('Something went wrong');
    if (snapshot.connectionState == ConnectionState.waiting)
      return CircularProgressIndicator();

    List<Map<String, dynamic>> newResult = snapshot.data.data();
    print(newResult);
    return SizedBox();
  },
)

【讨论】:

    【解决方案2】:

    Streams 非常有用,并且提供了许多开箱即用的优雅解决方案。

    在你的情况下,我会使用 StreamTransformer 来做这样的事情:

    Stream<CustomType> stream = _geo.collection(collectionRef: collectionReference)
       .within(center: center, radius: radius, field: field)
       .transform(StreamTransformer.fromHandlers(handleData: (docSnap, sink) {
          if (docSnap.exists) {
             sink.add(<convert docSnap fields to CustomType here>);
          }
    }));
    

    您可以使用 Streams 和 StreamTransformers 做更多事情,让您的代码更易于阅读和调试,而且更漂亮。关于 StreamTransformers 的文档: https://api.flutter.dev/flutter/dart-async/StreamTransformer-class.html

    编辑:免责声明,此答案基于 Stream 文件类而不是 geo flutter fire - 我没有经验。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-27
      • 2021-08-18
      • 1970-01-01
      • 2021-05-20
      • 2020-09-04
      相关资源
      最近更新 更多