Объединение нескольких потоков firebase во флаттере

Парень, это настоящая проблема слияния нескольких потоков firebase в один поток. Кто-то должен написать по этому поводу статью или простой видеоурок. Либо с помощью StreamGroup, FlatMap (), Rx.combineLatest, StreamZip или CombineLatestesStream. Я пытался решить эту проблему со вчерашнего дня и не могу получить четких указаний.

class CartPage extends StatefulWidget{
   @override
   _CartPageState createState() => _CartPageState();
}
class _CartPageState extends State<CartPage> {
   
   // a firebase collection for all items
   Stream stream1 = EcommerceApp.firestore
    .collection("items")
    .where("shortInfo",
        whereIn: EcommerceApp.sharedPreferences
            .getStringList(EcommerceApp.userCartList))
    .snapshots();

   // a firebase collection for flash sales items
   Stream stream2 = EcommerceApp.firestore
    .collection("flashitem")
    .where("shortInfo",
        whereIn: EcommerceApp.sharedPreferences
            .getStringList(EcommerceApp.userCartList))
    .snapshots();

   List<QuerySnapshot> getList(QuerySnapshot list1) {
   List<QuerySnapshot> result = [];
   (list1 as List).forEach((element) {
     result.add(element);
    });
     return result;
   }

 @override
 Widget build(BuildContext context) {

  Stream combineStream = Rx.combineLatest2(streamA, streamB, (a, b) => [a, b]);


   return Scaffold(
    appBar: MyAppBar(),
    body:CustomScrollView(
      slivers: [
        SliverToBoxAdapter(
          child: Container(
            height: 10.0,
          ),
        ),
       StreamBulder(
       stream: combineStream,
        builder: (context, snapshot) {
              if (!snapshot.hasData) {
                return SliverToBoxAdapter(
                  child: Center(
                    child: circularProgressBar(),
                  ),
                );
              } else {
              List<QuerySnapshot> _list = [];
                _list.addAll(getList(snapshot.data[0]));
                _list.addAll(getList(snapshot.data[1]));
                if (_list.length == 0) {
                } else {
                  return SliverList(
                    delegate: SliverChildBuilderDelegate(
                      (context, index) {
                        ProductModel model = ProductModel.fromJson(
                           _list[index].docs[index].data());

                        return cartSourceInfo(model, context,
                            removeCartFunction: () =>
                                removeItemFromUserCart(model.shortInfo));
                      },
                      childCount: childCount: snapshot.hasData ? _list.length : 0,
                    ),
                  );
                }
              }
            }    
       )
    );
 }
}

Большинство ответов здесь используют библиотеку Observable, которая исчерпана в rxdart, и когда я пытаюсь использовать тот же синтаксис для решения с использованием Rx.latestCombine2, потоковая передача данных отсутствует. и когда я пытаюсь передать querySnapshot списка типов в поток Stream ‹List›, я получаю пакет ошибок:

Класс List не имеет экземпляра получателя docs. Получатель: Экземпляр (длина: 2) из ​​'_GrowableList' Попытка вызвать: docs

Пожалуйста, покажите мне, как я могу вложить эти два потока firebase в ome или как я могу использовать метод Rx.combineLatest2 для решения этой проблемы.


person Alex Maina    schedule 22.04.2021    source источник
comment
Проблема в том, что я не знаю, как объединить несколько потоков в один поток. Я думаю, что что-то упускаю.   -  person Alex Maina    schedule 22.04.2021


Ответы (1)


Синтаксис выглядит правильно, но при попытке доступа к данным каждого потока вы должны обращаться к ним по индексу, поскольку снимок в основном представляет собой список

поэтому для доступа к моментальному снимку stream1 и stream2 он должен быть доступен следующим образом

snapshot.data[0].docs и snapshot.data[1].docs соответственно.

Вы можете объединить оба потока и отобразить список в пользовательском интерфейсе. Убедитесь, что назначили соответствующий тип T в зависимости от типа snapshot.data[index].docs


 List<QuerySnapshot> combineLists(
      List<QuerySnapshot> list1, List<QuerySnapshot> list2) {
    List<QuerySnapshot> result = [];
    list1.forEach((element) {
      result.add(element);
    });
    list2.forEach((element) {
      result.add(element);
    });
    return result;
  }

StreamBulder(
 ​stream: combineStream,
 ​builder: (context, AsyncSnapshot<List<QuerySnapshot>> snapshot) {
   ​if (!snapshot.hasData) {
      ​return SliverToBoxAdapter(
        ​child: Center(
          ​child: circularProgressBar(),
          ​),
        ​);
      ​} else {​
         final List<QuerySnapshot> _list=[];
         final List<QuerySnapshot> combineSnapshot =
                    combineLists(snapshot.data[0], snapshot.data[1]);
         ​if (_list.length == 0) {
            ​return addItems();
         ​} else {
             return SliverList(
                ​delegate: SliverChildBuilderDelegate(
                (context, index) {
                     ProductModel model = ProductModel.fromJson(
                     _list[index].data());
                 return cartSourceInfo(model, context, removeCartFunction: 
                    () => removeItemFromUserCart(model.shortInfo));
                 ​},
                 childCount:_list.length,
                 ),
               );
           ​}
        }
   }
person Mahesh Jamdade    schedule 22.04.2021
comment
Пока все хорошо, мне удалось получить доступ к снимку двух потоков. Большое тебе спасибо. Но теперь как мне обновить свой childCount, чтобы подсчитать длину обоих потоков. Я пробовал (snapshot.data [0] .docs.length + snapshot.data [1] .docs.length), но получаю - RangeError (index): Invalid value: only valid value is 0: 1 - person Alex Maina; 22.04.2021
comment
cna вы добавите более подробную информацию к своему вопросу, какие данные вы пытаетесь отобразить в пользовательском интерфейсе, из какой коллекции и какова структура коллекции? - person Mahesh Jamdade; 22.04.2021
comment
вы хотите показать данные обоих потоков в списке? - person Mahesh Jamdade; 22.04.2021
comment
Согласно вашему ответу выше, внутри SliverchildBuilderDelegate я создал два объекта ProductModel model = ProductModel.fromJson(snapshot.data[0].docs[index].data()); ProductModel flashSalemodel = ProductModel.fromJson(snapshot.data[1].docs[index].data()); Когда я использую один объект, он работает хорошо, но когда я использую оба объекта, я получаю RangeError (index): Invalid value: Only valid value is 0: 1 - person Alex Maina; 22.04.2021
comment
Я обновил проверку ответа, просто назначьте тип proprt T - person Mahesh Jamdade; 22.04.2021
comment
Большое спасибо, я думаю, что это последняя проблема, с которой я столкнулся, я пробовал использовать QuerySnapshot и DocumentSnapshot в качестве возвращаемого типа T, хотя получаю «type QuerySnapshot» не является подтипом типа «List ‹dynamic›» в приведении типов «и» тип DocumentSnapshot не является подтипом типа QuerySnapshot в приведении типов соответственно. В противном случае ваша логика имеет смысл на 100% - person Alex Maina; 22.04.2021
comment
вы можете сказать мне, что это за тип снимка? - person Mahesh Jamdade; 22.04.2021
comment
Это список документов, поэтому тип QuerySnapshot - person Alex Maina; 22.04.2021
comment
Я обновил ответ - person Mahesh Jamdade; 23.04.2021
comment
Мы изменили наш снимок на AsyncSnapshot List<QuerySnapshot>, поэтому я получаю эту ошибку. Тип аргумента «QuerySnapshot» не может быть назначен типу параметра «List ‹QuerySnapshot›». и как добавить документы в пустой _list, который мы создали. - person Alex Maina; 23.04.2021
comment
проверьте строку, где именно вы получаете ошибку, и затем мы можем изменить тип соответствующим образом - person Mahesh Jamdade; 23.04.2021
comment
окончательный список ‹QuerySnapshot› combSnapshot = combLists (snapshot.data [0], snapshot.data [1]); Оба параметра мы передаем в combLists. - person Alex Maina; 23.04.2021