Demo 效果图
方案选型——MQTT
在开始这片文章之前,首先来介绍一下我们今天的两位主角🤪:
主角一号(IM):即时通讯(Instant Messaging)
主角二号(MQTT):MQTT(Message Queuing Telemetry Transport,消息队列遥测传输协议),是一种基于发布/订阅(publish/subscribe)模式的"轻量级"通讯协议,该协议构建于TCP/IP协议上,由IBM在1999年发布。MQTT最大优点在于,可以以极少的代码和有限的带宽,为连接远程设备提供实时可靠的消息服务。
其实在实现项目内的IM功能时有多种选择,为什么选择MQTT
呢?🤔首先是考虑到我们项目的多端一致性,我们的项目有多个终端,在其中一个端中已经采纳了MQTT方案成功接入并实现了功能,后续可能打通多端的对话,所以我在自己的项目内也打算采用MQTT
➕消息推送
的方案。还有一个重要的原因:MQTT有库!有库!
MQTT Client 接入
Step1:MQTTAppConnectionState
首先需要明确的是MQTT的连接状态,这部分通俗易懂,在MQTT可能的状态有连接,未连接,正在连接。用枚举的方式将他们都列举出来。
enum MQTTAppConnectionState { connected, disconnected, connecting }
复制代码
非常好!已经完成了第一步,思路逐渐明确👀
Step2:MQTTAppState
有了MQTT的连接状态之后,还需的是什么呢?我们知道连接状态的目的是什么?当然是在连接成功的时候收发消息,连接断开的时候停止收发消息,并且在收到消息时我们要知道我们要知道,我们收到了什么消息。那我们需要的就是这样一个类,我们叫他MQTTAppState。
class MQTTAppState with ChangeNotifier{
MQTTAppConnectionState _appConnectionState = MQTTAppConnectionState.disconnected;
String _receivedText = '';
String _historyText = '';
void setReceivedText(String text) {
_receivedText = text;
_historyText = _historyText + '\n' + _receivedText;
notifyListeners();
}
void setAppConnectionState(MQTTAppConnectionState state) {
_appConnectionState = state;
notifyListeners();
}
String get getReceivedText => _receivedText;
String get getHistoryText => _historyText;
MQTTAppConnectionState get getAppConnectionState => _appConnectionState;
}
复制代码
在这个类中各位可以看到我们定义了我们当前收到的消息receivedText
和我们收到的历史消息_historyText
,我们定义这两个消息,我们的历史消息其实是一个叠加、换行的过程,每收到一条新消息,我们在原有的基础上加入这个新消息形成一个新的历史消息。同时我们也定义了方法去管理MQTTAppConnectionState.重点!🚩我们的这个类已经继承了ChangeNotifier,熟悉Flutter的同学也都能猜到,这是为了我们方便之后的全局状态管理,没错,这里用的也是Provider技术方案。
Step3:MQTTManager
需要接入一个功能,一个类库,首先你要有一个全局管理的思想,否则在Flutter这样的框架中你会让自己的UI和业务逻辑很难区分开来。这里的MQTTManager目的就是统一管理你的IM消息收发和消息订阅,作为一个全局manager类,首先我们需要的是定义构造函数,构造函数里一般会放置一个类的必要内容,对于一个MQTT来说,一个必备的类是什么呢?这里需要大家对MQTT有基础的了解,这里我先把答案写给大家。
MQTTManager({
@required String host,
@required String topic,
@required String identifier,
@required MQTTAppState state
}
): _identifier = identifier, _host = host, _topic = topic, _currentState = state ;
复制代码
对于一个MQTT最基础的配置包括host(host地址)
、topic(订阅主题)
、identifier(用户身份)
、state(连接状态)
其实这些大家仔细想一下不难理解,这是我们要做到收发消息,区分收件人、发件人的一些基础配置。
我们还需要一个MQTT服务器!🔧,同样我们需要加入服务器的基础配置
void initializeMQTTClient(){
_client = MqttServerClient(_host,_identifier);
_client.port = 1883;
_client.keepAlivePeriod = 20;
_client.onDisconnected = onDisconnected;
_client.secure = false;
_client.logging(on: true);
_client.onConnected = onConnected;
_client.onSubscribed = onSubscribed;
final MqttConnectMessage connMess = MqttConnectMessage()
.withClientIdentifier(_identifier)
.withWillTopic('willtopic') set a will message
.withWillMessage('My Will message')
.startClean()
.withWillQos(MqttQos.atLeastOnce);
_client.connectionMessage = connMess;
}
复制代码
这样一个简单的服务器我们已经给他配置好了基础配置,例如端口号,连接保持时长等,所有信息配置好之后,再给manager加上一些基础的管理方法就可以了。
MQTT的使用
在我们以上不懈努力下,接下来的一切都显得顺理成章,信手捏来🚅,结合上我们的页面知识。我们可以通过Manager实现我们的MQTT连接
_connectMQTT()
{
manager = MQTTManager(
host: "test.mosquitto.org",
topic: "flutter/amp/cool",
identifier: _userName,
state: currentAppState);
manager.initializeMQTTClient();
manager.connect();
}
复制代码
同时,由于我们已经集成了ChangeNaotifier,我们可以动态的监听我们所订阅的消息🦀,轻轻松松,两行代码。
//当前收到的消息
appState.getReceivedText
//所有历史消息
appState.getHistoryText
复制代码
发送消息也很简单,一行代码,搞定~😏
mqttManager.publish(message);
复制代码
整个MQTT框架搭建完成,配上一个炫酷的登录页面,配上一个类似微信的聊天界面,效果正是非常可以了。
项目地址
你把你的star🌟给我交了!哈哈哈哈哈
MQTT Demo
尾声
其实这只是一个简单的MQTT实现方案,大家在体验时可能会遇到消息收发延迟的问题,虽然不是很明显但是也会影响用户体验,这是什么原因呢?🤨因为我们遗忘了我们的好朋友——后端小伙伴,实际开发中,我们要和后端小伙伴合作我们的IM策略,往往是通过后端接口实现IM消息的发送,并且封装我们的监听部分。具体的方案我会在后续开发过程中持续更新,欢迎关注哦~🤩