Flutter-Firestore 将 Stream<List<DocumentSnapshot<Map<String, dynamic>>>> 转换为 List<MyClass>
Flutter-Firestore transform Stream<List<DocumentSnapshot<Map<String, dynamic>>>> into List<MyClass>
我创建了一个函数,我想 return 数据库中半径内的所有位置。这就是我使用 GeoFlutterFire 的原因。我的问题是我不知道如何将 Stream>>>
转换为 List<>我的 Class 类型。
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.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
returns 未来,您可能希望将流转换为未来。在这种情况下,您可以使用它。
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();
},
)
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 和 StreamTransformer 做更多事情,让您的代码更易于阅读和调试,而且更漂亮。关于 StreamTransformer 的文档:
https://api.flutter.dev/flutter/dart-async/StreamTransformer-class.html
编辑:免责声明,此答案基于 Stream 文件 类 而不是 geo flutter fire - 我对此没有经验。
我创建了一个函数,我想 return 数据库中半径内的所有位置。这就是我使用 GeoFlutterFire 的原因。我的问题是我不知道如何将 Stream>>>
转换为 List<>我的 Class 类型。
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.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
returns 未来,您可能希望将流转换为未来。在这种情况下,您可以使用它。
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();
},
)
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 和 StreamTransformer 做更多事情,让您的代码更易于阅读和调试,而且更漂亮。关于 StreamTransformer 的文档: https://api.flutter.dev/flutter/dart-async/StreamTransformer-class.html
编辑:免责声明,此答案基于 Stream 文件 类 而不是 geo flutter fire - 我对此没有经验。