फ़्लटर में एक और स्ट्रीम के लिए एक इनपुट के रूप में फायरबेस स्ट्रीम का उपयोग करना?

Dec 31 2020

संदर्भ: मुझे दो फायरबेस स्ट्रीम मिले हैं जो सही तरीके से काम करते हैं, और वे मुझे प्राप्त करते हैं) उपयोगकर्ता प्रोफाइल ('उपयोगकर्ताओं का संग्रह), और ii) प्रत्येक उपयोगकर्ता प्रोफ़ाइल (' स्थानों 'संग्रह) से संबंधित स्थानों की एक सूची, और फिर उन्हें कस्टम उपयोगकर्ता और स्थान मॉडल पर मैप करें।

उपयोगकर्ता स्ट्रीम:

class DatabaseService {

final String uid;
final String friendUid;
final String locationId;
DatabaseService({ this.uid, this.locationId, this.friendUid });

// collection reference for users
final CollectionReference userCollection = FirebaseFirestore.instance.collection('users');

// get users stream
Stream<List<CustomUserModel>> get users {

final FirebaseAuth auth = FirebaseAuth.instance;
final User user = auth.currentUser;
final uid = user.uid;

List<CustomUserModel> userList = [];

List<CustomUserModel> _streamMapper(DocumentSnapshot snapshot) {
  CustomUserModel individualUser = CustomUserModel(
    uid: snapshot.id,
    name: snapshot.data()['name'],
    username: snapshot.data()['username'],
    email: snapshot.data()['email'],
  );
  userList.add(individualUser);
  return userList;
}

  return userCollection.doc(uid).snapshots().map(_streamMapper);
}

और स्थान स्ट्रीम:

  // collection reference for location
   final CollectionReference locationCollection = 
   FirebaseFirestore.instance.collection('locations');

  Stream<List<Location>> get locations {

  final FirebaseAuth auth = FirebaseAuth.instance;
  final User user = auth.currentUser;
  final uid = user.uid;

  List<Location> _locationListFromSnapshot(QuerySnapshot snapshot) {
   List<Location> locationList = [];
    snapshot.docs.forEach((element) {
     Location individualLocation = Location(
       locationId: element.id,
       locationName: element.data()['locationName'],
       city: element.data()['city'],
     );
    locationList.add(individualLocation);
  });
   return locationList;
 }

  return userLocationCollection.doc(uid).collection('locations').snapshots()
   .map(_locationListFromSnapshot);
 }

मैं जो करना चाहता हूं वह एक कस्टम स्ट्रीम उत्पन्न करना है जो सभी उपयोगकर्ताओं के लिए सभी स्थानों को आउटपुट करता है - दूसरे शब्दों में उपयोगकर्ताओं को स्ट्रीम स्ट्रीम के लिए इनपुट के रूप में उपयोग करने के लिए।

मुझे यकीन नहीं है कि यहां क्या दृष्टिकोण काम करता है - मैंने उपयोगकर्ताओं को स्ट्रीम स्ट्रीम में इनपुट पैरामीटर के रूप में जोड़ने पर विचार किया और फिर फॉर-लूप का निर्माण किया, कुछ इस प्रकार है:

Stream<List<Location>> allLocations(Stream<List<CustomUserModel>> users) {

final FirebaseAuth auth = FirebaseAuth.instance;
final User user = auth.currentUser;
final uid = user.uid;

List<Location> locationList = [];

users.forEach((element) {

// append user's locations to empty list
locationList.add(locationCollection.doc(element.first.uid).collection('locations')
.snapshots().map(SOME FUNCTION TO MAP A DOCUMENT SNAPSHOT TO THE CUSTOM LOCATION MODEL)

}

return locationList;

लेकिन निश्चित रूप से मुझे एक त्रुटि मिलती है क्योंकि यह एक सूची देता है, एक धारा नहीं। इसलिए मुझे नहीं पता कि कैसे आगे बढ़ना है ...

जवाब

4 dshukertjr Dec 31 2020 at 07:52

मैं आपका दर्द सुनता हूं। मैं वहां जा चुका हूं। आप काफी करीब थे। मुझे समझाएं कि मुझे यह कैसे करना पसंद है।

सबसे पहले, कुछ साफ:

ऐसा लगता था कि आप इन allLocationsकार्यों में उपयोग नहीं कर रहे थे , इसलिए मैंने उन्हें हटा दिया

final FirebaseAuth auth = FirebaseAuth.instance;
final User user = auth.currentUser;
final uid = user.uid;

दूसरा, मैंने फ़ंक्शन का रिटर्न प्रकार बदल दिया Stream<List<Location>>है Stream<Map<String, List<Location>>जहां से मानचित्र की कुंजी उपयोगकर्ता आईडी होगी। मुझे यह प्रकार उपयोगी लगता है, क्योंकि आपको उपयोगकर्ताओं को स्ट्रीम के साथ सिंक करने के क्रम के बारे में चिंता करने की आवश्यकता नहीं है।

तीसरा, जब आप धाराएँ बना रहे होते हैं, तो आप वापस नहीं लौट सकते, लेकिन एक फंक्शन से उपज लेनी होती है। आपको फ़ंक्शन को भी चिह्नित करना होगा async*(* एक टाइपो नहीं है)।

इसके साथ, मैं प्रस्ताव करता हूं कि आप अपने allLocationsकार्य के लिए कुछ इस तरह का उपयोग करें :

class DataService {
  List<Location> convertToLocations(QuerySnapshot snap) {
    // This is the function to convert QuerySnapshot into List<Location>
    return [Location()];
  }

  Stream<Map<String, List<Location>>> allLocations(
      Stream<List<CustomUserModel>> usersStream) async* {
    Map<String, List<Location>> locationsMap = {};

    await for (List<CustomUserModel> users in usersStream) {
      for (CustomUserModel user in users) {
        final Stream<List<Location>> locationsStream = locationCollection
            .doc(user.uid)
            .collection('locations')
            .snapshots()
            .map(convertToLocations);
        await for (List<Location> locations in locationsStream) {
          locationsMap[user.uid] = locations;
          yield locationsMap;
        }
      }
    }
  }
}

मुझे उम्मीद है कि आपको यह तरीका पसंद आएगा। कृपया मुझे बताएं कि क्या कुछ ऐसा नहीं है जो आप चाहते हैं। मैं समायोजन कर सकता हूं।