Как именно объединить несколько потоков в firebase firestore

Прежде чем вы скажете, что это повторяющийся вопрос или что мне следует использовать построители вложенных потоков, выслушайте меня.

Я разрабатываю приложение для социальных сетей. И я хочу, чтобы пользователи получали обновления всякий раз, когда кто-то следит за сообщениями в моей коллекции сообщений подписчиков. В приложении приложение проверит firebase rtdb на предмет следующего списка текущего пользователя (людей, за которыми он подписан) и составит список их uid.

Я планирую использовать указанный список для создания списка потоков (конечно, упорядоченных по времени) и объединения их в один поток, который затем будет загружен в конструктор потоков на странице частного канала.

На этой странице пользователь сможет легко следить за тем, что публикуют его интересы.

Я полагал, что такая система намного более рентабельна, чем каждый пользователь, имеющий документ в частной коллекции каналов, и всякий раз, когда кто-то что-то публикует, приложение читает их список подписчиков, а затем быстро публикует обновление в каждом из их личных каналов. . Потому что ... Представьте кого-нибудь с 2 миллионами подписчиков. Это 2 миллиона записей мгновенно. А потом 2 миллиона прочтений. Я подумал, что для постера намного более экономично просто разместить сообщение в своей общедоступной ленте, а разные подписчики просто слушают эту ленту и следят за вкладками с ними.

Но .. Для этого необходимо реализовать объединение нескольких потоков (более 2-х). Как мне это сделать?

Я пробовал читать в RxDart, но для меня он полностью греческий. Я относительно новичок в дартсе. Я кодирую всего около 5 месяцев.


person Simeon    schedule 20.08.2020    source источник


Ответы (2)


Вы можете использовать StreamGroup из асинхронного пакета: https://pub.dev/documentation/async/latest/async/StreamGroup-class.html для группировки событий из нескольких потоков - это хорошо документировано и поддерживается командой dart. Если у вас нет опыта RxDart, это хороший выбор. У него нет всех функций rx, но для новичка должно быть легче понять это

person mgapinski    schedule 20.08.2020
comment
Не могли бы вы привести мне простой пример, как это сделать. Я полностью изучаю руководство по YouTube, так что я еще не настолько хорошо разбираюсь в способах написания документации. Я лучше учусь на примерах. Предположим, у вас есть данные в новой коллекции Cars, некоторые другие данные в newClothesCollection и некоторые другие данные в коллекции newKeyBoards. Не могли бы вы написать немного демонстрационного кода о том, как вы могли бы использовать async, чтобы объединить эти три и передать их в конструктор потоков? - person Simeon; 22.08.2020
comment
Мне удалось объединить потоки, используя это, и это действительно работает. Однако я столкнулся с новой и совершенно другой проблемой, связанной с отображением объединенного потока в построителе потоков. Я собираюсь опубликовать это как новый вопрос. Спасибо. - person Simeon; 24.08.2020

Недавно у меня был похожий случай, и я предлагаю вам сделать следующее (я использую облачный хранилище, но я уверен, что ваши потоки уже написаны, поэтому важной частью является использование нескольких потоков):

Вам необходимо добавить этот плагин в pub spec.yaml: https://pub.dev/packages/rxdart

Вот репозиторий для (в вашем случае сообщений, скажем, newPosts, oldPosts):

class PostRepository {

  static CollectionReference get collection => yourCollectionRef;
    
  static Stream<List<Post>> newPosts() {
    Query query = collection
        .where('Your condition like was viewed', isEqualTo: false)
        .orderBy('updateDate', descending: true)
        .limit(50);
    return query.snapshots().map<List<Post>>((querySnapshot) {
      final _newPosts = querySnapshot.documents.map((doc) {
        final post = Post.fromDoc(doc);
        return post;
      }).where((p) => p != null);

      return _newPosts
    });
  }

  static Stream<List<Post>> oldPosts() {
    Query query = collection
        .where('Your condition like was viewed', isEqualTo: true)
        .orderBy('updateDate', descending: true)
        .limit(50);
    return query.snapshots().map<List<Post>>((querySnapshot) {
      final _oldPosts = querySnapshot.documents.map((doc) {
        final post = Post.fromDoc(doc);
        return post;
      }).where((p) => p != null);

      return _oldPosts
    });
  }
}

Затем, чтобы получить несколько потоков (эти два сверху вместе), сделайте это в своем классе виджета:

ВАЖНЫЙ! вам нужно импортировать это - import 'package: rxdart / streams.dart';

List<Post> newPosts;
List<Post> oldPosts;

Widget _pageContent() {
  return SingleChildScrollView(
    child: Column(
      children: [
        ListView.builder(
          shrinkWrap: true,
          physics: NeverScrollableScrollPhysics(),
          itemCount: newPosts.length,
          itemBuilder: (context, index) {
            return ListTile(
              title: Text(newPosts[index].title)
            );
          }
        ),
        ListView.builder(
          shrinkWrap: true,
          physics: NeverScrollableScrollPhysics(),
          itemCount: oldPosts.length,
          itemBuilder: (context, index) {
            return ListTile(
              title: Text(oldPosts[index].title)
            );
          }
        )
      ]
    )
  );
}

Widget _posts() {
  return StreamBuilder(
    stream: CombineLatestStream.list([
      PostRepository.getNewPosts(),
      PostRepository.getOldPosts()
    ]),
    builder: (context, snap) {
     if (snap.hasError) {

        debugPrint('${snap.error}');
        return ErrorContent(snap.error);

      } else if (!snap.hasData) {

        return Center(
          child: CircularProgressIndicator(),
        );

      }

      newPosts = snap.data[0];
      oldPosts = snap.data[1];

      return _pageContent();
    }
  );
}

Я написал код как с головы, поэтому могут быть небольшие ошибки, но надеюсь, вы поняли суть, наслаждайтесь :)

person Nonstapp    schedule 20.08.2020
comment
Большое спасибо. Хотя я не думаю, что можно поместить представление списка в представление прокрутки. Я делал это раньше, и это дает некоторую ошибку в том смысле, что вы не можете поместить прокручиваемый объект внутри другого прокручиваемого манекена. Я собираюсь опробовать ваше решение и дать вам отзыв. - person Simeon; 22.08.2020
comment
Ok. Если вы используете shrinkwrap и neverscrollablescrollphysics, как в примере, ваши 2 списка должны вести себя идеально, как вы хотите :) - person Nonstapp; 22.08.2020
comment
Большое спасибо. Мне удалось объединить потоки с помощью группы потоков, но в настоящее время я столкнулся с новой проблемой с отображением этого объединенного потока в построителе потоков. Но я публикую это как совершенно новый вопрос. Спасибо тебе. - person Simeon; 24.08.2020
comment
Обратите внимание, что если вы хотите объединить потоки коллекции (Stream ‹List ‹T››, а не Stream ‹T›, вам нужно использовать настраиваемую функцию объединения - в этом примере он вызывает CombineLatestStream.list, который использует объединитель по умолчанию, что хорошо для Stream ‹T›. В моем случае я не мог заставить его работать, пока не понял, что при использовании Stream ‹List ‹T›› вам нужно предоставить настраиваемый комбайнер для его обработки (получите список ‹List ‹T››, затем сгладьте его, чтобы получить список потоков ‹T› ›по мере необходимости) .Так что вам нужно использовать обычный CombineLatestStream(streamList, combinerFunc). - person Guy; 13.02.2021