Jaguar_websocket结合Flutter搭建简单聊天室
1.定义消息
在开始建立webSocket之前,我们需要定义消息,如:发送人,发送时间,发送人id等..
import 'dart:convert';
class ChatMessageData {
final String id;
final String msg;
final DateTime created;
final String name;
final int role;
ChatMessageData(
this.id,
this.msg,
this.name,
this.role,
this.created,
);
static ChatMessageData formMap(Map map) => ChatMessageData(
map['id'],
map['msg'],
map['name'],
map['role'],
DateTime.fromMicrosecondsSinceEpoch(map['created'])); Map toMap() => {
"id": id,
"msg": msg,
"name": name,
"role":role,
"created": created.millisecondsSinceEpoch
};
String toJson() => jsonEncode(toMap());
@override
String toString() => toMap().toString();
}
我们这里定义了一个ChatMessageData,如果你想需要更多字段,可以再添加
2.添加消息订阅
//控制消息的发送
final pub = StreamController<ChatMessageData>();
//当pub调用add(data)方法,该sub的listen会监听到
final Stream<ChatMessageData> sub = pub.stream.asBroadcastStream();
3. 定义接口
这里我们定义两个接口,一个用于连接的接口,一个用于发送消息的接口
/mini/login 提交用户的信息,如果不正确,返回相关的信息,不给连接
/min/connect 连接websocket,该接口获取到websocket对象,然后可以使用该对象
进行发送消息
登陆接口
..post('/mini/login', (ctx) async{
User user=await ctx.bodyAsJson(convert: User.forMap);
String username = user.username;
String password = user.password;
if (username.isEmpty || password.isEmpty) {
return Response.json(apiJson.errorMsgA(-, '用户名或密码为空!').toMap());
} else {
User user = await userBean.findOneWhere(userBean.username.eq(username));
if (user == null || user.password != password) {
return Response.json(apiJson.errorMsgA(-, '用户名或密码不正确!').toMap());
} else {
print('用户:$username登陆成功');
return Response.json(apiJson.successA().toMap());
}
}
})
连接接口
..ws(
'/mini/connect',
onConnect: (ctx, ws) {
var subscription = sub.listen((ChatMessageData data) {
print(data.toJson());
ws.add(data.toJson());
});
ws.done.then((_) {
print('用户已退出聊天房');
subscription.cancel();
});
//连接上之后返回一条信息
ws.add(new ChatMessageData('', '欢迎登陆', '服务器', , DateTime.now()).toJson());
},
handler: (data) {
//获取用户发送的消息
ChatMessageData msg=ChatMessageData.formMap(json.decode(data));
print(msg.toJson());
//广播一条消息
pub.add(msg);
},
)
ok,我们已经搭建好一个简单的聊天接口了,下面,我们使用Flutter简单的编辑一下客户端平台
4.Flutter建立一个简单的聊天室
这部分代码为Flutter下,可简单的编辑一个聊天室
mport 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; void main() {
runApp(new FriendlychatApp());
} final ThemeData kIOSTheme = new ThemeData(
primarySwatch: Colors.orange,
primaryColor: Colors.grey[],
primaryColorBrightness: Brightness.light,
); final ThemeData kDefaultTheme = new ThemeData(
primarySwatch: Colors.purple,
accentColor: Colors.orangeAccent[],
); const String _name = "Your Name"; class FriendlychatApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: "Friendlychat",
theme: defaultTargetPlatform == TargetPlatform.iOS
? kIOSTheme
: kDefaultTheme,
home: new ChatScreen(),
);
}
} class ChatMessage extends StatelessWidget {
ChatMessage({this.text, this.animationController});
final String text;
final AnimationController animationController;
@override
Widget build(BuildContext context) {
return new SizeTransition(
sizeFactor: new CurvedAnimation(
parent: animationController,
curve: Curves.easeOut
),
axisAlignment: 0.0,
child: new Container(
margin: const EdgeInsets.symmetric(vertical: 10.0),
child: new Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
new Container(
margin: const EdgeInsets.only(right: 16.0),
child: new CircleAvatar(child: new Text(_name[])),
),
new Expanded(
child: new Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
new Text(_name, style: Theme.of(context).textTheme.subhead),
new Container(
margin: const EdgeInsets.only(top: 5.0),
child: new Text(text),
),
],
),
),
],
),
)
);
}
} class ChatScreen extends StatefulWidget {
@override
State createState() => new ChatScreenState();
} class ChatScreenState extends State<ChatScreen> with TickerProviderStateMixin {
final List<ChatMessage> _messages = <ChatMessage>[];
final TextEditingController _textController = new TextEditingController();
bool _isComposing = false; void _handleSubmitted(String text) {
_textController.clear();
setState(() {
_isComposing = false;
});
ChatMessage message = new ChatMessage(
text: text,
animationController: new AnimationController(
duration: new Duration(milliseconds: ),
vsync: this,
),
);
setState(() {
_messages.insert(, message);
});
message.animationController.forward();
} void dispose() {
for (ChatMessage message in _messages)
message.animationController.dispose();
super.dispose();
} Widget _buildTextComposer() {
return new IconTheme(
data: new IconThemeData(color: Theme.of(context).accentColor),
child: new Container(
margin: const EdgeInsets.symmetric(horizontal: 8.0),
child: new Row(children: <Widget>[
new Flexible(
child: new TextField(
controller: _textController,
onChanged: (String text) {
setState(() {
_isComposing = text.length > ;
});
},
onSubmitted: _handleSubmitted,
decoration:
new InputDecoration.collapsed(hintText: "Send a message"),
),
),
new Container(
margin: new EdgeInsets.symmetric(horizontal: 4.0),
child: Theme.of(context).platform == TargetPlatform.iOS
? new CupertinoButton(
child: new Text("Send"),
onPressed: _isComposing
? () => _handleSubmitted(_textController.text)
: null,
)
: new IconButton(
icon: new Icon(Icons.send),
onPressed: _isComposing
? () => _handleSubmitted(_textController.text)
: null,
)),
]),
decoration: Theme.of(context).platform == TargetPlatform.iOS
? new BoxDecoration(
border:
new Border(top: new BorderSide(color: Colors.grey[])))
: null),
);
} Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("Friendlychat"),
elevation:
Theme.of(context).platform == TargetPlatform.iOS ? 0.0 : 4.0
),
body: new Container(
child: new Column(
children: <Widget>[
new Flexible(
child: new ListView.builder(
padding: new EdgeInsets.all(8.0),
reverse: true,
itemBuilder: (_, int index) => _messages[index],
itemCount: _messages.length,
)
),
new Divider(height: 1.0),
new Container(
decoration: new BoxDecoration(
color: Theme.of(context).cardColor),
child: _buildTextComposer(),
),
]
),
decoration: Theme.of(context).platform == TargetPlatform.iOS ? new BoxDecoration(border: new Border(top: new BorderSide(color: Colors.grey[]))) : null),//new
);
}
}
上面就是简单的聊天界面,我们还有主要跟服务器交互的方法
WebSocket socket;
void login() {
httpManager.post(
url: 'http://192.168.1.101:8080/mini/login',
body: json.encode({
"username": "rhyme",
"password": "",
}),
onSend: () {
//key为scaffold的key
scaffoldKey?.currentState
?.showSnackBar(new SnackBar(content: Text('发送请求,连接服务器')));
},
onSuccess: (data) {
WebSocket.connect('ws://192.168.1.101:8080/mini/connect')
.then((socket) {
this.socket = socket;
socket.listen((data) {
//该方法接收服务器信息
print(data);
Map map = json.decode(data);
ChatMessageData msg=ChatMessageData.formMap(map);
if(msg.id!=widget.user.uuid){
_handleGetMessage(msg);
}
});
socket.done.then((e){
//当与服务器连接中断调用
scaffoldKey.currentState.showSnackBar(new SnackBar(content: Text('连接服务器中断!')));
});
});
},
onError: (error) {
print(error);
scaffoldKey.currentState.showSnackBar(
new SnackBar(content: Text('连接失败!${error.toString()}')));
});
}
我们发送消息给服务端
socket.add(new ChatMessageData(widget.user.uuid, value, widget.user.userName, widget.user.role, DateTime.now()).toJson());
最后我们来尝试一下吧!


Jaguar_websocket结合Flutter搭建简单聊天室的更多相关文章
- SpringBoot 搭建简单聊天室
SpringBoot 搭建简单聊天室(queue 点对点) 1.引用 SpringBoot 搭建 WebSocket 链接 https://www.cnblogs.com/yi1036943655/p ...
- ASP.NET SingalR + MongoDB 实现简单聊天室(一):搭建基本框架
ASP.NET SingalR不多介绍.让我介绍不如看官网,我这里就是直接上源代码,当然代码还是写的比较简单的,考虑的也少,希望各位技友多多提意见. 先简单介绍聊天室功能: 用户加入聊天室,自动给用户 ...
- Python Socket 简单聊天室2
上篇文章写了一个简单的单线程的一问一答的简单聊天室.这次我们使用SocketServer模块搭建一个多线程异步的聊天室. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ...
- 基于Server-Sent Event的简单聊天室 Web 2.0时代,即时通信已经成为必不可少的网站功能,那实现Web即时通信的机制有哪些呢?在这门项目课中我们将一一介绍。最后我们将会实现一个基于Server-Sent Event和Flask简单的在线聊天室。
基于Server-Sent Event的简单聊天室 Web 2.0时代,即时通信已经成为必不可少的网站功能,那实现Web即时通信的机制有哪些呢?在这门项目课中我们将一一介绍.最后我们将会实现一个基于S ...
- SilverLight搭建WCF聊天室详细过程[转]
http://www.silverlightchina.net/html/zhuantixilie/getstart/2011/0424/7148.html 默认节点 SilverLight搭建WCF ...
- Asp.Net SignalR - 简单聊天室实现
简单聊天室 使用持久链接类我们就可以做一些即时通讯的应用了,我使用Group做了一个简单的聊天室,先上图技术细节下面再讲 可以加入聊天室.创建聊天室.发送消息,下面就说说我是如何通过Group做出来的 ...
- 利用socket.io+nodejs打造简单聊天室
代码地址如下:http://www.demodashi.com/demo/11579.html 界面展示: 首先展示demo的结果界面,只是简单消息的发送和接收,包括发送文字和发送图片. ws说明: ...
- C#实例之简单聊天室(状态管理)
前言 状态管理是在同一页或不同页的多个请求发生时,维护状态和页信息的过程.因为Web应用程序的通信协议使用了无状态的HTTP协议,所以当客户端请求页面时,ASP.NET服务器端都会重新生 ...
- java web利用mvc结构实现简单聊天室功能
简单聊天室采用各种内部对象不适用数据库实现. 一个聊天室要实现的基本功能是: 1.用户登录进入聊天室, 2.用户发言 3.用户可以看见别人发言 刚才算是简单的需求分析了,现在就应该是进 ...
随机推荐
- 理解web service 和 SOA
什么是SOA? SOA的全称为Service Oriented Architecture,即面向服务架构.这是一种架构理念.它的提出是在企业计算领域将耦合的系统划分为松耦合的无状态的服务.服务发布出来 ...
- STL简洁 && c++读取cfg文件
在c++工程中,往往需要修改一些变量来实现不同的功能效果,这是cfg文件的使用可以使得工程更加高效与便利,这篇文章介绍的就是c++读取cfg文件的相关内容,以便及时总结和日后回顾. STL即标准模板库 ...
- Android_EditText 打勾显示输入的密码 --EditText与setTransformationMethod
实现目标: 实现原理: 为CheckBox添加一个监听器事件; 实现的源码: package edu.cquptzx.showPassword; import android.app.Activity ...
- JavaScript -- Location
-----043-Location.html----- <!DOCTYPE html> <html> <head> <meta http-equiv=&quo ...
- 第三方登录:微信扫码登录(OAuth2.0)
1.OAuth2.0 OAuth(开放授权)是一个开放标准,允许用户让第三方应用访问该用户在某一网站上存储的私密的资源(如照片,视频,联系人列表),而无需将用户名和密码提供给第三方应用. 允许用户提供 ...
- 【转载】表单中 Readonly 和 Disabled 的区别
今天写代码,遇到表单提交的问题,某个字段在不同的情况下,要传递不同的值进行赋值,试过一些方法都有些问题,后来请教前端同学,使用 disabled 这个属性终于搞定了问题,查到一篇讲解 readonly ...
- 微信小程序开发语言的选择
微信使用的开发语言和文件很「特殊」. 小程序所使用的程序文件类型大致分为以下几种: ①WXML(WeiXin Mark Language,微信标记语言) ②WXSS(WeiXin Style Shee ...
- 查看Linux 版本
如何得知自己正在使用的linux是什么版本呢,下面的几种方法将给你带来答案! 1. 查看内核版本命令: 1) [root@q1test01 ~]# cat /proc/version Linux v ...
- 版本管理(一)之Git和GitHub的区别(优点和缺点)
Git 简介 https://www.yiibai.com/git/getting-started-git-basics.html Git 是一个开源的分布式版本控制系统,用于敏捷高效地处理任何或小或 ...
- Spring-Task思维导图
最近在搞一个定时任务的相关东西,为了方便记忆,这里将知识点总结成一个思维导图.后续也会通过思维导图的方式发布博客.