这是我的集团代码

我想创建的实时聊天功能与拉威尔API,推进器,并与一个信号.我的所有代码运行正常,除了当我向聊天用户发送新消息时,用户收到我的消息,我能够打印消息和数据,但收件人用户的用户界面没有为新消息更新.

            import 'package:flutter/material.dart';
            import 'package:soulsphere/bloc/chat/chat_message_state.dart';
            import 'package:flutter_bloc/flutter_bloc.dart';
            import 'package:soulsphere/repositories/chats/chat_messages_repo.dart';
            import 'package:soulsphere/model/chat_message.dart';
            
            class ChatMessageCubit extends Cubit<ChatMessageState>{
              final BuildContext context;
              final String chatUserID;
            
              ChatMessageCubit({
                required this.context,
                required this.chatUserID,
              }) : super(ChatMessageLoadingState()){
                fetchChatMessage(context, chatUserID);
              }
            
              ChatMessageRepository chatMessageRepository = ChatMessageRepository();
            
              void fetchChatMessage(BuildContext context, String? chatUserID) async{
                print("========================================");
                print("in fetch chat message api");
                  try{
                    print("fetch message for: $chatUserID");
                    if(chatUserID != 0){
                      List<ChatMessage> chatMessages = await chatMessageRepository.fetchChatsFromApi(context, chatUserID);
                      emit(ChatMessageLoadedState(chatMessages));
                    }
                    else{
                      emit(ChatMessageErrorState("No Chat User Found"));
                    }
                  }
                  catch (ex){
                    emit(ChatMessageErrorState(ex.toString()));
                  }
              }
            
              void sendMessage(BuildContext context, String message, String chatUserID) async {
                try{
                  List<ChatMessage> sentMessage = (await chatMessageRepository.sendMessage(context, message, chatUserID)).cast<ChatMessage>();
                  emit(ChatMessageLoadedState(sentMessage));
                }
                catch (ex){
                  emit(ChatMessageErrorState(ex.toString()));
                }
              }
            
              void addNewMessageFromPusher(Map<String, dynamic> messageData) {
                print("in add new message from pusher");
                if (state is ChatMessageLoadedState) {
                  ChatMessage newMessage = ChatMessage.fromJson(messageData);
                  List<ChatMessage> currentMessages = List.from((state as ChatMessageLoadedState).chatMessages);
                  currentMessages.add(newMessage);
                  print("============================================================");
                  print("============================================================");
                  emit(ChatMessageLoadedState(currentMessages));
                }
              }
            
            
            }

和我的聊天屏幕代码

        import 'package:flutter/material.dart';
import 'package:pusher_client/pusher_client.dart';
import 'package:soulsphere/controller/laravel_echo/laravel_echo.dart';
import 'package:soulsphere/screens/users/user_view.dart';
import 'package:soulsphere/utils/app_constants.dart';
import 'package:soulsphere/model/user.dart';
import 'package:soulsphere/model/chat_message.dart';
import 'package:shimmer/shimmer.dart';
import 'dart:convert';
import 'package:soulsphere/utils/show_toast.dart';
import 'package:soulsphere/utils/shared_pref.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:soulsphere/bloc/chat/chat_message_cubit.dart';
import 'package:soulsphere/bloc/chat/chat_message_state.dart';


class ChatDetailsScreen extends StatefulWidget {
  final User user;

  const ChatDetailsScreen({
    Key? key,
    required this.user,
  }) : super(key: key);

  @override
  State<ChatDetailsScreen> createState() => _ChatDetailsScreenState();
}

class _ChatDetailsScreenState extends State<ChatDetailsScreen> {
  bool isLoading = true;
  late String userID;
  bool isChatDataFetched = true;
  late ChatMessageCubit chatMessageCubit;

  void listenChatChannel(chatID) {
    LaravelEcho.instance.channel('chat.$chatID').listen(
      '.message.sent',
          (e) {
        if (e is PusherEvent) {
          if (e.data != null) {
            Map<String, dynamic> messageData = json.decode(e.data!);
            print("in function listen channel");
            print(messageData);
            chatMessageCubit.addNewMessageFromPusher(messageData);
          }
        }
      },
    ).error((err) {
      showToast(context, 'Pusher error: $err');
    });
  }

  void leaveChatChannel(chatID){
      try{
          LaravelEcho.instance.leave('chat.$chatID');
      }
      catch(err){
        showToast(context, err.toString());
      }
  }

  @override
  void initState() {
    super.initState();
    getUserDataFromSharedPreferences();
    String chatID = widget.user.chatID.toString();

    // Initialize chatMessageCubit before using it in listenChatChannel
    chatMessageCubit = ChatMessageCubit(context: context, chatUserID: widget.user.userID.toString());

    listenChatChannel(chatID);
  }

  @override
  void dispose() {
    String chatID = widget.user.chatID.toString();
    leaveChatChannel(chatID);
    chatMessageCubit.close();
    super.dispose();
  }

  // ------- make UserID variable for using in build ------- //
  Future<void> getUserDataFromSharedPreferences() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    setState(() {
      userID = prefs.getString(CustomSharedConstants.userID) ?? '';
    });
  }


  @override
  Widget build(BuildContext context) {
    User user = widget.user;

    return BlocProvider(
      create: (context) => ChatMessageCubit(context: context, chatUserID: widget.user.userID.toString()),
      child: Scaffold(
        appBar: AppBar(
          title: Text(user.userName ?? AppConstants.noUserName),
          backgroundColor: Colors.transparent,
          flexibleSpace: Container(
            decoration: const BoxDecoration(
              gradient: AppColors.bgColorGradient,
            ),
          ),
          actions: [
            PopupMenuButton(
              itemBuilder: (context) {
                return [
                  const PopupMenuItem(
                    value: 'profile',
                    child: Text('View Profile'),
                  ),
                  const PopupMenuItem(
                    value: 'settings',
                    child: Text('Settings'),
                  ),
                ];
              },
              onSelected: (value){
                if(value == 'profile'){
                  Navigator.push(context, MaterialPageRoute(builder: (context) => UserProfileScreen(user: user)));
                }
              },
            ),
          ],
        ),
        body: BlocBuilder<ChatMessageCubit, ChatMessageState>(
          key: const Key('chatMessagesKey'),
          builder: (context, state) {
            if(state is ChatMessageLoadingState){
              print("in loading state");
              return const Center(child: CircularProgressIndicator());
            }
            else if (state is ChatMessageLoadedState){
              print("in loaded state");
              return Column(
                children: [
                  Expanded(
                    child: SingleChildScrollView(
                      child: ChatMessages(messages: state.chatMessages, userId: userID),
                    ),
                  ),
                  ChatInputField(
                    onSendMessage: (message, chatUserID) {
                      context.read<ChatMessageCubit>().sendMessage(context, message, chatUserID);
                    },
                    chatUserID: widget.user.userID.toString(),
                    onUpdateChatMessages: (updatedMessages) {
                      // Implement the logic to update messages if needed
                    },
                  ),
                ],
              );
            }
            else if(state is ChatMessageErrorState){
              return Center(child: Text('Error: ${state.error}'));
            }
            else{
              return const Center(child: Text('Failed to load data from API'));
            }
          },
        ),
      ),
    );
  }
}

class ShimmerEffect extends StatelessWidget {
  const ShimmerEffect({super.key});

  @override
  Widget build(BuildContext context) {
    return Shimmer.fromColors(
      baseColor: Colors.grey[300]!,
      highlightColor: Colors.grey[100]!,
      child: ListView.builder(
        shrinkWrap: true,
        physics: const NeverScrollableScrollPhysics(),
        itemCount: 10,
        itemBuilder: (BuildContext context, int index) {
          return ListTile(
            title: Container(
              width: 200.0,
              height: 20.0,
              color: Colors.white,
            ),
          );
        },
      ),
    );
  }
}

class ChatMessages extends StatelessWidget {
  final List<ChatMessage> messages;
  final String userId;

  const ChatMessages({
    Key? key,
    required this.messages,
    required this.userId,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return ListView.builder(
      shrinkWrap: true,
      physics: const NeverScrollableScrollPhysics(),
      itemCount: messages.length,
      itemBuilder: (BuildContext context, int index) {
        return ChatBubble(
          message: messages[index].messageText!,
          isMe: messages[index].userID.toString() == userId,
        );
      },
    );
  }
}

class ChatBubble extends StatelessWidget {
  final String message;
  final bool isMe;

  const ChatBubble({
    Key? key,
    required this.message,
    required this.isMe,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Align(
      alignment: isMe ? Alignment.centerRight : Alignment.centerLeft,
      child: Container(
        margin: const EdgeInsets.all(8.0),
        padding: const EdgeInsets.all(12.0),
        decoration: BoxDecoration(
          color: isMe ? Colors.blue : Colors.grey[300],
          borderRadius: BorderRadius.circular(10.0),
        ),
        child: Text(
          message,
          style: TextStyle(color: isMe ? Colors.white : Colors.black),
        ),
      ),
    );
  }
}

class ChatInputField extends StatefulWidget {
  final Function(String, String) onSendMessage;
  final String chatUserID;
  final Function(List<ChatMessage>) onUpdateChatMessages;

  const ChatInputField({
    Key? key,
    required this.onSendMessage,
    required this.chatUserID,
    required this.onUpdateChatMessages,
  }) : super(key: key);

  @override
  State<ChatInputField> createState() => _ChatInputFieldState();
}

class _ChatInputFieldState extends State<ChatInputField> {
  bool _isSending = false;
  final _messageController = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.white,
      padding: const EdgeInsets.all(8.0),
      child: Row(
        children: [
          IconButton(
            icon: const Icon(Icons.attach_file),
            onPressed: () {
              // Handle attachment button press
            },
          ),
          Expanded(
            child: TextFormField(
              controller: _messageController,
              decoration: const InputDecoration(
                contentPadding: EdgeInsets.all(15.0),
                hintText: 'Type a message...',
                border: InputBorder.none,
              ),
            ),
          ),
          IconButton(
            icon: _isSending
                ? const CircularProgressIndicator(
              valueColor: AlwaysStoppedAnimation<Color>(Colors.blue),
            )
                : const Icon(Icons.send),
            onPressed: _isSending
                ? null
                : () async {
                      setState(() {
                        _isSending = true;
                      });
                      String message = _messageController.text;
                      await widget.onSendMessage(message, widget.chatUserID);
                      setState(() {
                        _isSending = false;
                        _messageController.clear();
                      });
                    },
          ),
        ],
      ),
    );
  }
}


我已经try 了很多代码的更改.

                void listenChatChannel(chatID) {
                  LaravelEcho.instance.channel('chat.$chatID').listen(
                    '.message.sent',
                        (e) {
                      if (e is PusherEvent) {
                        if (e.data != null) {
                          Map<String, dynamic> messageData = json.decode(e.data!);
                          print("in function listen channel");
                          print(messageData);
                          chatMessageCubit.addNewMessageFromPusher(messageData);
                        }
                      }
                    },
                  ).error((err) {
                    showToast(context, 'Pusher error: $err');
                  });
                }

当目标用户收到新消息时触发此代码

推荐答案

您正在使用不同的ChatMessageCubit实例.您可以将相同的ChatMessageCubit实例传递给所有BlocBuilder.您正在您的initState中创建一个chatMessageCubit实例.只需将相同的实例传递给BlocBuilder.下面给出了示例代码.

BlocProvider(
      create: (context) => chatMessageCubit,
      child: Scaffold(
        appBar: AppBar(
          title: Text(user.userName ?? AppConstants.noUserName),
          backgroundColor: Colors.transparent,
          flexibleSpace: Container(
            decoration: const BoxDecoration(
              gradient: AppColors.bgColorGradient,
            ),
          ),

Flutter相关问答推荐

类型flatter doctor get zsh:未找到命令:macO中flatter

Firebase Auth异常未被catch捕获

Flutter版本3.19.2需要更新版本的Kotlin Gradle插件./android/build.gradle:ext.kotlin_version = latest-version>'

如何将assets资源 实体类型转换为文件类型?

使用Ffltter CREATE创建项目时,androidManifest.xml中缺少包属性

Flutter Android Google Sign-in error:ApiException:10在确认软件包名称、SHA-1 fingerprint 和设置同意页面后出现异常

Flutter 未处理的异常 - 对 null 值使用 Null 判断运算符

允许文本小部件在容器之间溢出

Riverpod中stateNotiferProvider和notifierProvider的区别

如何将行推到列的底部

如何在 Flutter 中滚动时为多个小部件设置动画

Riverpod 在使用冻结副本更新状态时触发重建,即使没有任何更改

SfCircularChart 周围的额外间距

无法在 flutter 中更新 void 方法内的变量值

如何在 flutter 中更改日期 Select 器 colored颜色 ?

如何在 ListView.builder 中扩展文本?

无法列出 com.facebook.android:facebook-login -Facebook 登录问题的版本

Flutter 上Denim blue colored颜色 的 colored颜色 矩阵代码是什么?

如何使用 Riverpod 在运行时动态创建提供程序?

将容器扩展到安全区域 - Flutter