Поток внутри потока с использованием провайдеров - PullRequest
0 голосов
/ 24 декабря 2018

Итак, я создал структуру BLOC с потоком, как показано ниже.Сборщик получит изменения в список идентификаторов чата.Затем, используя преобразователь, он добавил бы данные в потоке на карту кэша и направил их на выход.

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

   class ChatRoomBloc {
    // this is similar to the Streambuilder and Itemsbuilder we have in the Stories bloc
      final _chatroomsFetcher = PublishSubject<String>();
      final _chatroomsOutput =
          BehaviorSubject<Map<String, Observable<ChatroomModel>>>();

// Getter to Stream
  Observable<Map<String, Observable<ChatroomModel>>> get chatroomStream =>
      _chatroomsOutput.stream;

  ChatRoomBloc() {
    chatRoomPath.listen((chatrooms) => chatrooms.documents
        .forEach((f) => _chatroomsFetcher.sink.add(f.documentID)));
    _chatroomsFetcher.stream
        .transform(_chatroomsTransformer())
        .pipe(_chatroomsOutput);
  }

  ScanStreamTransformer<String, Map<String, Observable<ChatroomModel>>>
      _chatroomsTransformer() {
    return ScanStreamTransformer(
        (Map<String, Observable<ChatroomModel>> cache, String id, index) {
      // adding the iteam to cache map
      cache[id] = chatRoomInfo(id);
      print('cache ${cache.toString()}');
      return cache;
    }, <String, Observable<ChatroomModel>>{});
  }

  dispose() {
    _chatroomsFetcher.close();
    _chatroomsOutput.close();
  }
}

Observable<ChatroomModel> chatRoomInfo(String _chatrooms) {
  final _chatroomInfo = PublishSubject<ChatroomModel>();

  Firestore.instance
      .collection('chatRooms')
      .document(_chatrooms)
      .snapshots()
      .listen((chatroomInfo) =>
          _chatroomInfo.sink.add(ChatroomModel.fromJson(chatroomInfo.data)));

  dispose() {
    _chatroomInfo.close();
  }

  return _chatroomInfo.stream;
}

Затем я создаю Streambuilder с представлением списка, чтобы вывести список идентификаторов и любые данные из соответствующих им потоков, как показано ниже.

class FeedList extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final chatroomBloc = ChatRoomProvider.of(context);
    return Scaffold(
      appBar: AppBar(
        title: Text('Chat Room'),
      ),
      body: buildList(chatroomBloc),
    );
  }
  Widget buildList(ChatRoomBloc chatroomBloc) {
    return StreamBuilder(
        // Stream only top ids to display
        stream: chatroomBloc.chatroomStream,
        builder: (context,
            AsyncSnapshot<Map<String, Observable<ChatroomModel>>> snapshot) {
          if (!snapshot.hasData) { // no data yet
            return Center(child: CircularProgressIndicator());
          }
          return ListView.builder(
            itemCount: snapshot.data.length,
            itemBuilder: (context, int index) {
              print('index $index and ${snapshot.data}');
              return buildTile(snapshot.data[index]);
            },
          );
        });
  }

  Widget buildTile(Observable<ChatroomModel> chatroomInfoStream) {
    return StreamBuilder(
        stream: chatroomInfoStream,
        builder: (context, AsyncSnapshot<ChatroomModel> chatroomSnapshot) {
          if (!chatroomSnapshot.hasData) {
            return Center(
              child: CircularProgressIndicator(),
            );
          }
          print('${chatroomSnapshot.data.name}');
          print('${chatroomSnapshot.data.members.toString()}');
          return Column(children: [
            ListTile(
              title: Text('${chatroomSnapshot.data.name}'),
              trailing: Column(
                children: <Widget>[
                  Icon(Icons.comment),
                ],
              ),
            ),
            Divider(
              height: 8.0,
            ),
          ]);
        });
  }
}

Вывод, который я получаю, приведен ниже.Streambuilder застревает в CircularProgressIndicator в методе buildTile.Я думаю, это означает, что экземпляры создаются и добавляются в карту кеша, но они много прислушиваются к правильным экземплярам или что-то не так в том, как я подключил потоки.Можете ли вы помочь?

I/flutter (12856): cache {H8j0EHhu2QpicgFDGXYZ: Instance of 'PublishSubject<ChatroomModel>'} 
I/flutter (12856): cache {H8j0EHhu2QpicgFDGXYZ: Instance of 'PublishSubject<ChatroomModel>', QAhKYk1cfoq8N8O6WY2N: Instance of 'PublishSubject<ChatroomModel>'} 
I/flutter (12856): index 0 and {H8j0EHhu2QpicgFDGXYZ: Instance of 'PublishSubject<ChatroomModel>', QAhKYk1cfoq8N8O6WY2N: Instance of 'PublishSubject<ChatroomModel>'} 
I/flutter (12856): index 1 and {H8j0EHhu2QpicgFDGXYZ: Instance of 'PublishSubject<ChatroomModel>', QAhKYk1cfoq8N8O6WY2N: Instance of 'PublishSubject<ChatroomModel>'}

1 Ответ

0 голосов
/ 24 декабря 2018

В качестве быстрого исправления, возможно, попробуйте:

final _chatroomInfo = BehaviorSubject<ChatroomModel>();

На втором примечании:

Код в его текущем состоянии трудно читать и понимать, он не поддерживается инеэффективен.Я не уверен, что вы на самом деле пытаетесь сделать.

Это плохая идея вкладывать StreamBuilder s.Это задержит отображение списка чата как минимум на 2 кадра, потому что каждый StreamBuilder отображает хотя бы один пустой кадр (data = null).

Прослушивание потока и подача результата в Subject также добавит задержки.

Если возможно, попробуйте удалить все объекты.Вместо этого используйте операторы rx.

BLoC должен предоставлять один выходной поток, который предоставляет все данные, необходимые для отображения списка чатов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...