Mar*_* Dz 5 flutter bloc flutter-bloc twilio-conversations flutter-streambuilder
我是 bloc 的新手,正在尝试使用包实现聊天flutter_bloc。我的消息传递服务是 twilio Conversations api。我的功能运行得很好,我只是无法刷新我的消息列表。有人可以告诉我我在这里缺少什么吗?如果我访问聊天页面,我可以看到所有消息,只有当我们有新消息时它才不会刷新。
由于取得了小小的成功,我更新了我的代码。每当用户 A 或用户 B 加入聊天时,都会显示所有消息。如果我以用户 A 的身份发送消息,则该消息现在将在用户 A 的 UI 中可见,并且它是对话的一部分,但用户 B 在不重新加载的情况下不会收到添加到对话中的新消息。这里缺少哪个步骤以便其他用户也收到消息?我只需要帮助转换我的代码,以便我有一个流,聊天的其他参与者可以收听,这样他们的对话也令人耳目一新。
\n我的 chat_event.dart
\n abstract class ChatEvent extends Equatable{\n const ChatEvent();\n\n @override\n List<Object> get props => [];\n}\n\nclass InitialChatEvent extends ChatEvent {}\n\nclass AddMessage extends ChatEvent {\n final String messageToPost;\n\n AddMessage(this.messageToPost);\n}\nRun Code Online (Sandbox Code Playgroud)\n我的 chat_state.dart
\n class ChatState extends Equatable {\n final Messages messages;\n\n const ChatState({required this.messages});\n\n factory ChatState.initial() => ChatState(messages: Messages(messages: []));\n\n @override\n List<Object> get props => [messages];\n\n @override\n bool get stringify => true;\n\n ChatState copyWith({\n List<Messages>? messages,\n }) {\n return ChatState(\n messages: this.messages,\n );\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n聊天页面的一部分
\n...\nExpanded(\n child: BlocBuilder<ChatBloc, ChatState>(\n builder: (context, state) {\n print('chatpage builder: ' + state.messages.toString());\n return ListView.builder(\n itemCount: state.messages.messages.length,\n scrollDirection: Axis.vertical,\n itemBuilder: (context, i) {\n return ListTile(\n tileColor: state.messages.messages[i].author.toString() == username ? Colors.amber : Colors.amber.shade100,\n title: Text(\n state.messages.messages[i].body.toString(),\n style: TextStyle(color: Colors.black),\n ),\n );\n });\n },\n ),\n ),\n ...\n Container(\n height: 50,\n padding: EdgeInsets.fromLTRB(10, 0, 10, 0),\n child: RaisedButton(\n textColor: Colors.white,\n color: Colors.red,\n child: Text('Button'),\n onPressed: () async {\n // print(chatMessage.text);\n context.read<ChatBloc>().add(AddMessage(chatMessage.text));\n },\n )),\n ],\n...\nRun Code Online (Sandbox Code Playgroud)\nchat_bloc.dart
\nclass ChatBloc extends Bloc<ChatEvent, ChatState> {\n \n ChatBloc() : super(ChatState.initial()) {\n // print('wird ausgef\xc3\xbchrt');\n on<InitialChatEvent>((event, emit) async {\n final chatFeed = await HttpService().getMessages();\n emit(ChatState(messages: chatFeed));\n });\n \n on<AddMessage>((event, emit) async {\n final newConversation = await HttpService().postMessage(event.messageToPost);\n final chatFeed = await HttpService().getMessages();\n emit(ChatState(messages: chatFeed));\n });\n }\n}\nRun Code Online (Sandbox Code Playgroud)\nmain.dart(如果需要)
\n...\n\nvoid main() => runApp(MultiBlocProvider(\n providers: [\n BlocProvider(create: (context) => ColorBloc()),\n BlocProvider(create: (context) => ChatBloc()),\n ],\n child: MaterialApp(\n title: "App",\n home: MyApp(),\n )));\n\nclass MyApp extends StatefulWidget {\n @override\n State<MyApp> createState() => _MyAppState();\n}\n\nclass _MyAppState extends State<MyApp> {\n // This widget is the root of your application.\n TextEditingController nameController = TextEditingController();\n\n @override\n Widget build(BuildContext context) {\n return Scaffold(\n body: Column(\n children: [\n ...\n child: RaisedButton(\n textColor: Colors.white,\n color: Colors.red,\n child: Text('Button'),\n onPressed: () {\n print(nameController.text);\n context.read<ChatBloc>().add(InitialChatEvent());\n Navigator.of(context).push(\n MaterialPageRoute(\n builder: (context) => ChatPage(userText: nameController.text)\n ),\n );\n },\n )),\n ],\n ),\n );\n }\n}\nRun Code Online (Sandbox Code Playgroud)\nhttp_service.dart
\n Future postMessage(String messageToPost) async {\n Map<String, String> _messageToPost = {\n 'Author': 'User A',\n 'Body': messageToPost,\n };\n\n try {\n // print(messageToPost);\n\n var response = await dio.post(\n "https://conversations.twilio.com/v1/Conversations/$sid/Messages",\n data: _messageToPost,\n options: Options(\n contentType: Headers.formUrlEncodedContentType,\n headers: <String, String>{'authorization': basicAuth},\n ));\n\n return messageToPost;\n } catch (e) {\n print('exception: ' + e.toString());\n Future.error(e.toString());\n }\n }\n\n Future getMessages() async {\n try {\n final response = await dio.get(\n "https://conversations.twilio.com/v1/Conversations/$sid/Messages",\n // data: _messageToPost,\n options: Options(\n // contentType: Headers.formUrlEncodedContentType,\n headers: <String, String>{'authorization': basicAuth},\n ));\nprint(response.data);\n final messageList = Messages.fromJson(response.data);\n print(messageList);\n return messageList;\n } catch (e) {\n print('exception: ' + e.toString());\n return Future.error(e.toString());\n }\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n
这个问题没有简短的答案,如果我必须在这里写出完整的过程,那就太冗长和多余了。其他人已经写了完整的教程,比如这个很棒的教程: https: //blog.codemagic.io/flutter-ui-socket/。但是,这可能会错过您感兴趣的 BLoC 部分。因此,下面我将描述如何使用此链接中提供的示例并使用 BLoC 改进它。
您将需要创建一个 ChatBloc 和一个 Socket。我更喜欢创建一个 Socket Singletone,以确保在应用程序的整个生命周期中始终只有一个套接字连接:D。
旁注
我承认可能还有其他方法可以做到这一点。在这里,我正在解释我的方法;)为了简单起见,我根据上面链接的书面教程旋转了下面的示例;)
Will包含基本的消息事件:
SendMessageGetMessageLoadHistoryUpdateConnectedUsers这里我将重点讨论最敏感的一个(即您关心的问题)。那是,GetMessage。这里的秘密是调用这个事件,不是从 UI,而是从 Socket Singletone。换句话说,您的套接字将侦听传入的消息,每当收到消息时,它就会触发 ChatBloc 的“GetMessage”事件,而该事件又会更新 UI。这是一个实施尝试:
class SocketApi {
IO.Socket _socket;
//You need to inject an instance of the ChatBloc here so that you can
//call the 'GetMessage' event --- see comment below ;)
ChatBloc chatBloc;
/// We are creating a singleton here to make sure we have only one instance
/// of Io.io at all time
static final SocketApi _socketApi = SocketApi._internal();
SocketApi._internal() {
_socket = IO.io(<url_to_your_socket_Server>, <String, dynamic>{
'transports': ['websocket'],
'autoConnect': false,
});
// This is where the magic happens...
// you listen of incoming messages
// on the socket and then trigger the chatBloc event 'GetMessage'.
_socket.on('message', (data) {
// I am converting here to a chatMessage object...
// on your side you might have something like 'fromJson',
// etc..
ChatMessage chatMessage = chatMessageFromMap(data);
chatBloc.add(GetMessage(chatMessage));
});
}
//...
}
Run Code Online (Sandbox Code Playgroud)
现在剩下的就是在您需要在小部件树中匹配消息的位置添加 BlocBuilder 或 BlocSelector。
最后的重要说明 如果您真的很认真地使用 BLoC,我建议您检查与 bloc 库密切相关的 Freezed 软件包。它可以帮助您快速高效地构建模型。我与这个软件包的开发者没有任何关系,我也没有通过广告获得任何好处。它只是让我的生活更轻松,我绝对喜欢它提高我的代码质量的方式,并想分享 <3
干杯,祝你好运!
| 归档时间: |
|
| 查看次数: |
2215 次 |
| 最近记录: |