1倚舀、
網(wǎng)上找一圈,關(guān)于flutter及時(shí)通訊的文章太少了驹针。實(shí)際項(xiàng)目需要用socket io 來(lái)實(shí)現(xiàn)客戶(hù)端的消息收發(fā)言疗,服務(wù)端已經(jīng)寫(xiě)好了。
一開(kāi)始的思路是使用 socket io + 數(shù)據(jù)庫(kù)懦冰,但數(shù)據(jù)庫(kù)用起來(lái)是個(gè)麻煩事灶轰,其實(shí)socket io 目前現(xiàn)有的框架集成到項(xiàng)目中總是有各種各樣的bug和兼容問(wèn)題。
所以在折騰很久之后選擇了一個(gè)降級(jí)的socket io 庫(kù)刷钢。目前沒(méi)有發(fā)現(xiàn)什么問(wèn)題笋颤,結(jié)合eventbus實(shí)現(xiàn) 消息在客戶(hù)端的傳遞。
2内地、依賴(lài)
pubspec.yaml
# socket-io
adhara_socket_io: ^0.2.0
# 消息訂閱
event_bus: ^1.1.0
3伴澄、消息列表
一般是在首頁(yè),該頁(yè)面一般不會(huì)被銷(xiāo)毀阱缓,所以在該頁(yè)面注冊(cè)Event非凌,能保證消息的實(shí)時(shí)的接收,同時(shí)鏈接socket io查詢(xún)所有的聊天室荆针。
1敞嗡、
這里我封裝一個(gè)socketUtils來(lái)做消息接收的驗(yàn)證
on方法是接收事件颁糟,和服務(wù)端約定好對(duì)應(yīng)的key,然后在接收到消息后通過(guò)eventBus分發(fā)給相應(yīng)的頁(yè)面喉悴。
class SocketUtils {
static SocketIOManager manager;
static SocketIO socket;
static Future socketTo() async {
print('登錄IM');
manager = SocketIOManager();
//該部分需要根據(jù)自己實(shí)際業(yè)務(wù)實(shí)現(xiàn)
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();
}
//下面是客戶(hù)端發(fā)送數(shù)據(jù)包
//獲取會(huì)話列表
static getRooms() {
if (socket != null) {
print('獲取會(huì)話列表');
socket.emit('rooms', []);
}
}
//發(fā)送消息
static sendMsg(MessageBean messageBean) {
//實(shí)時(shí)更新到聊天界面
eventBus.fire(messageBean);
if (socket != null) {
socket.emit('sendMessage', [
{
'msg': messageBean.msg
}
}
]);
}
}
2棱貌、消息列表
在初始化的時(shí)候調(diào)用
SocketUtils.socketTo();
如果鏈接成功會(huì)自動(dòng)拉取一次getRooms(),當(dāng)然如果鏈接失敗箕肃,重試也可以直接使用該方法婚脱,或者鏈接成功,但是獲取rooms失敗勺像,那就直接調(diào)用
SocketUtils.getRooms();
然后在消息列表注冊(cè)eventbus的監(jiān)聽(tīng)
StreamSubscription streamSubscription;
streamSubscription = eventBus.on().listen((e) {
switch (e.runtimeType) {
case ResultEvent:
//會(huì)話列表
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 = '暫無(wú)消息';
}
});
break;
case MessageEvent:
//新消息
SocketUtils.getRooms();
break;
case UndoEvent:
//撤回
SocketUtils.getRooms();
break;
}
});
3起惕、消息詳情
同上,使用eventbus注冊(cè)監(jiān)聽(tīng)咏删,收到消息后分別處理