在 Streambuilder 中合并两个流和 return 一个 ListView (Flutter)

Combine two stream in Streambuilder and return a single ListView (Flutter)

我正在尝试将来自两个不同集合的两个流(第一个是 'avvenimenti',第二个是 'prospettive')组合成一个 return 一个 ListView 的 StreamBuilder。

我已经尝试了很多选项(使用 Rx、StreamBuilder return StremBuilder return ListView 等 ..)但未能使它们适应我的项目。

在 ListView 的子 属性 上,我只能添加一个列表:

return StreamBuilder(
      stream: Global.avvenimentiRef.streamData(),
      builder: (context, snap1) {
        if (snap1.hasData) {
          List<Avvenimento> avvenimenti = snap1.data;
          return StreamBuilder(
            stream: Global.prospettiveRef.streamData(),
            builder: (context, snap2) {
              if (snap2.hasData) {
                List<Prospettive> prospettive = snap2.data;
                return Scaffold(
                  //this is the single ListView i want to use
                  body: ListView(
                    primary: false,
                    padding: const EdgeInsets.only(top: 20, bottom: 20),
                    children: 
                    prospettive.map((prospettiveId) => ProspettiveItem(prospettiveId: prospettiveId)).toList(),
                    avvenimenti
                        .map((avvenimentoId) =>
                            AvvenimentoItem(avvenimentoId: avvenimentoId))
                        .toList(),
                  
                  ),
                );
              } else {
                return LoadingScreen();
              }
            },
          );
        } else {
          return LoadingScreen();
        }
      },
    );
  }

我的数据库:

lass Document<T> {
  final FirebaseFirestore _db = FirebaseFirestore.instance;
  final String path;
  DocumentReference ref;

  Document({this.path}) {
    ref = _db.doc(path);
  }

  Future<T> getData() {
    return ref.get().then((v) => Global.models[T](v.data()) as T);
  }

  Stream<T> streamData() {
    return ref.snapshots().map((v) => Global.models[T](v.data()) as T);
  }

  Future<void> upsert(Map data) {
    return ref.set(Map<String, dynamic>.from(data));
  }
}

class Collection<T> {
  final FirebaseFirestore _db = FirebaseFirestore.instance;
  final String path;
  CollectionReference ref;

  Collection({this.path}) {
    ref = _db.collection(path);
  }

  Future<List<T>> getData() async {
    var snapshot = await ref.get();
    return snapshot.docs
        .map((doc) => Global.models[T](doc.data()) as T)
        .toList();
  }

  Stream<List<T>> streamData() {
    return ref.snapshots().map((list) =>
        list.docs.map((doc) => Global.models[T](doc.data()) as T).toList());
  }
}

型号:

class ElencoProspettive {
  String fonte;
  String title;
  
  ElencoProspettive({this.fonte, this.title});

  ElencoProspettive.fromMap(Map data) {
    fonte = data['data'] ?? '';
    title = data['title'] ?? '';
  }
}

class Prospettive {
  String id;
  String titlePro;
  List<ElencoProspettive> elenco;

  Prospettive({this.id, this.titlePro, this.elenco});

  factory Prospettive.fromMap(Map data) {
    return Prospettive(
        id: data['data'] ?? '',
        titlePro: data['title'] ?? '',
        elenco: (data['elenco'] as List ?? [])
            .map((v) => ElencoProspettive.fromMap(v))
            .toList());
  }
}

型号:

class Global {
  //
  // App Data
  //
  static final String title = 'Annales';

  static final FirebaseAnalytics analytics = FirebaseAnalytics();

  static final Map models = {
    Avvenimento: (data) => Avvenimento.fromMap(data),
    Prospettive: (data) => Prospettive.fromMap(data),
  };

  static final Collection<Avvenimento> avvenimentiRef =
      Collection<Avvenimento>(path: 'avvenimenti');

  static final Collection<Prospettive> prospettiveRef =
      Collection<Prospettive>(path: 'propsettive');
}

使用 Rx 中的 CombineLatestStream 因为你提到你已经尝试过了。

StreamBuilder(
      stream: CombineLatestStream.list([
        Global.avvenimentiRef.streamData(),
        Global.prospettiveRef.streamData(),
      ]),
      builder: (context, snap1)
  • 请注意,如果其中一个流发生更改,您 StreamBuilder 将重新加载
  • 您可以使用 snap1.data[0]snap1.data[1] 等访问流返回的数据

列表,你可以试试

ListView(
                    primary: false,
                    padding: const EdgeInsets.only(top: 20, bottom: 20),
                    children: 
                    [...(prospettive.map((prospettiveId) => ProspettiveItem(prospettiveId: prospettiveId)).toList()),
                    ...(avvenimenti
                        .map((avvenimentoId) =>
                            AvvenimentoItem(avvenimentoId: avvenimentoId))
                        .toList())],
                  
                  ),