firebaseflutterdartgoogle-cloud-firestoregeohashing

Flutter-Firestore transform Stream<List<DocumentSnapshot<Map<String, dynamic>>>> into List<MyClass>


I made a function where I want to return all places in my database which are inside a radius. Thats why Im using GeoFlutterFire. My problem its that I dont know how to convert Stream<List<DocumentSnapshot<Map<String, dynamic>>>> into a List<> of my Class type.


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;

  }
}

Solution

  • 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();
    });
    

    Since getClientsList returns a future, you might want to convert the stream to a future. In that case, you can use this.

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

    Alternatively, you can listen to the stream using a stream builder. Something like this.

    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();
      },
    )