1、
网上找一圈,关于flutter及时通讯的文章太少了。实际项目需要用socket io 来实现客户端的消息收发,服务端已经写好了。
一开始的思路是使用 socket io + 数据库,但数据库用起来是个麻烦事,其实socket io 目前现有的框架集成到项目中总是有各种各样的bug和兼容问题。
所以在折腾很久之后选择了一个降级的socket io 库。目前没有发现什么问题,结合eventbus实现 消息在客户端的传递。
2、依赖
pubspec.yaml
# socket-io
adhara_socket_io: ^0.2.0
# 消息订阅
event_bus: ^1.1.0
3、消息列表
一般是在首页,该页面一般不会被销毁,所以在该页面注册Event,能保证消息的实时的接收,同时链接socket io查询所有的聊天室。
1、
这里我封装一个socketUtils来做消息接收的验证
on方法是接收事件,和服务端约定好对应的key,然后在接收到消息后通过eventBus分发给相应的页面。
class SocketUtils {
static SocketIOManager manager;
static SocketIO socket;
static Future socketTo() async {
print('登录IM');
manager = SocketIOManager();
//该部分需要根据自己实际业务实现
String token = await SPUtils.getToken();
print(token);
if(token!=null) {
token = token.substring(7);
}
print(token);
//配置socket链接信息
SocketOptions socketOptions = new SocketOptions(
Api.SOCKET_IO_URL,
query: {
'token': token,
'source': 'CONSULTANT',
},
transports: [Transports.WEB_SOCKET, Transports.POLLING],
enableLogging: false,
);
socket = await manager.createInstance(socketOptions);
socket.onConnect((res) {
print('onConnect--------socket链接成功---------');
getRooms();
});
socket.on('connect', (res) {
print('connect----------');
});
//房间列表
socket.on('rooms', (rooms) {
eventBus.fire(new ResultEvent(rooms));
});
//消息历史
socket.on('history', (data) {
LogUtil.e('消息历史:' + data.toString());
eventBus.fire(new MsgHistoryResultEvent(data));
});
socket.on('delete', (data) {
print('消息删除delete:' + data.toString());
});
socket.on('message', (data) {
print('新消息:' + data.toString());
eventBus.fire(new MessageEvent(data));
});
socket.connect();
}
//下面是客户端发送数据包
//获取会话列表
static getRooms() {
if (socket != null) {
print('获取会话列表');
socket.emit('rooms', []);
}
}
//发送消息
static sendMsg(MessageBean messageBean) {
//实时更新到聊天界面
eventBus.fire(messageBean);
if (socket != null) {
socket.emit('sendMessage', [
{
'msg': messageBean.msg
}
}
]);
}
}
2、消息列表
在初始化的时候调用
SocketUtils.socketTo();
如果链接成功会自动拉取一次getRooms(),当然如果链接失败,重试也可以直接使用该方法,或者链接成功,但是获取rooms失败,那就直接调用
SocketUtils.getRooms();
然后在消息列表注册eventbus的监听
StreamSubscription streamSubscription;
streamSubscription = eventBus.on().listen((e) {
switch (e.runtimeType) {
case ResultEvent:
//会话列表
setState(() {
msgList = [];
for (var i = e.data.length - 1; i >= 0; i--) {
msgList.add(new User.fromJson(e.data[i]));
}
if (e.data.length == 0) {
emptyText = '暂无消息';
}
});
break;
case MessageEvent:
//新消息
SocketUtils.getRooms();
break;
case UndoEvent:
//撤回
SocketUtils.getRooms();
break;
}
});
3、消息详情
同上,使用eventbus注册监听,收到消息后分别处理