源码解析博客推荐
https://juejin.im/post/5cd66c4af265da037516bec3
1.遇到的问题
1.1同一设备,多次创建mqtt client
在最开始的代码实现中,发现同一个设备有两个client。因为我在client的定义上有增加timestamp作为参数的一部分,而timestamp在获取的时候是根据当前时间动态获取的,这导致我在service多次启动中,创建了多个client。
在mqtt的client中,一个clientID可以创建一个mqtt的连接,如果出现了两个以上,那么说明一定是clientID不同导致的。
1.2断线重连导致陷入死循环
最开始设计断线重连的时候,client调用的callback是:mqttcallback,这个回调需要手动处理断线重连状态。
//订阅主题的回调【setAutomaticReconnect设置false调用该回调】
private MqttCallback mqttCallback = new MqttCallback() {
@Override
public void connectionLost(Throwable cause) {
LogUtils.d("mqtt", "mqttCallback>>连接中断");
//doClientConnect();//再次连接,这种写法会导致异常:不停的断线重连
// try {
// Thread.sleep(30000);
// reConnect();
// }catch (InterruptedException e){
// e.printStackTrace();
// }catch (Exception e){
// e.printStackTrace();
// }
}
@Override
public void messageArrived(String topic, MqttMessage message) throws Exception {
LogUtils.d("mqtt", "消息获得");
LogUtils.d("mqtt", "topic : " + topic);
LogUtils.d("mqtt", "message : " + message.toString());
}
@Override
public void deliveryComplete(IMqttDeliveryToken token) {
}
};
我在connectLost中再次做了
mqttAndroidClient.connect(mqttConnectOptions, null, mqttActionListener);
请求,这里会出现一个情况:
如果再次连接成功,那么mqtt会调用断开之前的连接,并再次做新的连接,然后陷入死循环。
原因:
这是一种异常情况,就是在断线连接之后的再次连接,创建了一个新的client,而新的client连接的时候,会导致之前的连接断开,会执行connectionLost方法,而connectionLost方法的执行又会再次连接,导致新的client断开,然后触发connectionLost,就陷入死循环。而这种异常情况的来源是两个client导致的。
所以,方法就是调用mqtt提供的断线重连方法,而非手动去断线重连。同时,避免创建两个client。
代码更改为:
mqttConnectOptions.setAutomaticReconnect(true);//断线重连
同时设置setCallback为:MqttCallbackExtended
MqttCallbackExtended会在断线重连成功之后调用
connectComplete
在方法里面重新订阅需要的topic,不然无法收到服务器的消息
这样也可以解决手动重连需要做循环导致UI线程阻塞的问题。
1.3关闭close mqtt的时候导致内存泄漏
https://blog.csdn.net/hacker_crazy/article/details/103489861
目前的解决方法是退出应用不关闭mqtt的service。
1.4 MQTT断开连接的时候调用顺序:
mqttAndroidClient.close();
mqttAndroidClient.unregisterResources();
try {
if (mqttAndroidClient != null) {
// LogUtils.d("mqtt", "clientId : " + mqttAndroidClient.getClientId());
mqttAndroidClient.disconnect();
//mqttAndroidClient.close();
}
} catch (Exception e) {
e.printStackTrace();
LogUtils.d("mqtt", "exception 1 : " + e.getLocalizedMessage());
}