天天看点

mqtt开发总结1.遇到的问题

源码解析博客推荐

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());
        }