天天看點

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