Как отобразить поток списка из блока, используя просмотр списка - PullRequest
0 голосов
/ 10 ноября 2019

Я работаю над приложением для обмена мгновенными сообщениями, и мне нужно, чтобы пользователь отправлял и получал сообщения в режиме реального времени. Я использую Firebase в качестве серверной части приложения, пакет flutter_bloc для управления состояниями и потоки для отправки и получения сообщений в режиме реального времени.

Я успешно реализовал функцию отправки сообщений и могу получитьсообщения успешно из Cloud Firestore, но когда пользователь отправляет сообщение, оно не загружается в сообщения чата ListView.

Это реализация метода ChatProvider getCurrentChatMessages(), который вызывается вChatBloc.

  Stream<List<ChatMessage>> getCurrentChatMessages() {
    return this.messagesRef.orderBy('timestamp', descending: true)
    .snapshots()
    .map((QuerySnapshot snapshot) {
      return snapshot.documents.map<ChatMessage>((DocumentSnapshot snapshot) => ChatMessage.fromFirestore(snapshot)).toList();
    });
  }

В ChatProvider это методы, которые распространяют список сообщений чата на пользовательский интерфейс

  Stream<ChatState> mapFetchCurrentChatMessagesEventToState(FetchCurrentChatMessagesEvent event) async* {
    yield FetchingCurrentChatMessagesState();
    final bool chatExists = await _chatProvider.chatExists;
    // If chat does not exists create chat.
    if (!chatExists) {
      await _chatProvider.createChat();
    }
    _chatProvider.getCurrentChatMessages().listen((List<ChatMessage> chatMessages) {
      print('Chat messages length: ${chatMessages.length}');
      dispatch(FetchedCurrentChatMessagesEvent(chatMessages));
    });
  }

  Stream<ChatState> mapFetchedCurrentChatMessagesEventToState(FetchedCurrentChatMessagesEvent event) async* {
    final List<ChatMessage> chatMessages = event.chatMessages;
    yield FetchedCurrentChatMessagesState(chatMessages);
  }

Это ListView, отображающийсообщения чата.

class ChatMessagesList extends StatefulWidget {
  @override
  _ChatMessagesListState createState() => _ChatMessagesListState();
}

class _ChatMessagesListState extends State<ChatMessagesList> {
  List<ChatMessage> _chatMessages = List<ChatMessage>();

  @override
  Widget build(BuildContext context) {
    return Expanded(
      child: BlocBuilder<ChatBloc, ChatState>(
        condition: (ChatState oldState, ChatState newState) => oldState.hashCode != newState.hashCode,
        builder: (BuildContext context, ChatState state) {
          if (state is FetchingCurrentChatMessagesState) {
            return Center(
              child: CircularProgressIndicator(),
            );
          }

          if (state is FetchedCurrentChatMessagesState) {
            _chatMessages = state.chatMessages;
          }

          if (_chatMessages.length == 0) {
            return Container();
          }

          print('Chat Messages:\n$_chatMessages');

          return ListView.builder(
            reverse: true,
            itemCount: _chatMessages.length,
            itemBuilder: (BuildContext context, int index) {
              final ChatMessage chatMessage = _chatMessages[index];
              return ChatMessageTile(
                chatMessage: chatMessage,
              );
            },
          );
        },
      ),
    );
  }
}

Всякий раз, когда отправляется сообщение, ChatBloc отправляет обновленный список сообщений чата на виджет ChatMessagesList, но виджет не обновляется соответствующим образом. Он отображает только первый элемент в списке _chatMessages, пока я не pop и push маршрут, то есть когда я увижу обновленный список.

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

1 Ответ

0 голосов
/ 11 ноября 2019

Используя потоковые контроллеры пакетов rxdart, например, BehaviourSubject, вы можете использовать свой список Пример в классе блока:

final _list = BehaviourSubject<List<ChatMessage>>(); //private variable
Observable<List<ChatMessage>> get list => _list.stream; //exposesvariable_publicly

exampleMethod(){ 
//prepare your list and when ready load the stream using sink
_list.sink.add(readylist);
}

Теперь в вашем списке просмотра используйте streambuilder

Widget _listView(){
 return StreamBuilder(){
   stream: blocProvider.list
   builder: (context, AsyncSnapshot<List<ChatMessage>> listSnapShot){
     //custom build your UI now with data in listSnapshot.data.

   }

Надеюсь, это поможет.

...