1. android 中使用MQTT(第一篇)
MQTT(Message Queuing Telemetry Transport,消息隊列遙測傳輸)是IBM開發的一個即時通訊協議。它是一種發布/訂閱,極其簡單和輕量級的消息傳遞協議,專為受限設備和低帶寬,高延遲或不可靠的網路而設計。它的設計思想是輕巧、開放、簡單、規范,易於實現。這些特點使得它對很多場景來說都是很好的選擇,特別是對於受限的環境如機器與機器的通信(M2M)以及物聯網環境。相對於XMPP,MQTT更加輕量級,並且佔用的寬頻低。
MQTT協議有以下特點:
那麼問題來了?重連連接成功後重復接收到最後一條消息
MQTT推送消息訂閱端重復接收問題。
(背景)訂閱端斷開的時候,發布端多次推送消息。
(現象)訂閱端啟動時,接收到最後一條推送消息有兩次;即使Qos設置為2;依然是兩次。
經排查是因為
MqttMessage的Retained設置為了true;
該值很多文章上只說了是 消息保留機制,若設置為true,mqtt伺服器會保留每次發布的消息;較少提到 若訂閱某主題的客戶端重啟,則會把此主題之前發布的消息重新推送到客戶端。該值默認為false;去掉修改該值即可
那麼問題來了?重連連接後手動那麼多遺漏的消息,怎麼選擇只接收最新的一條消息呢?
MQTT推送消息訂閱端重復接收問題。
(背景)訂閱端斷開的時候,發布端多次推送消息。
(現象)訂閱端啟動時,接收到msg1,msg2,msg3 (這三個消息都是同一個類型消息,只需要處理最新的msg3就好,不然界面會刷新三次)這個誰有什麼好辦法沒呢?
GitHub地址: https://github.com/eclipse/paho.mqtt.android
mqtt的官方文檔: http://mqtt.org/documentation
Github上有中文翻譯: https://github.com/mcxiaoke/mqtt
在mole的build.gradle文件中添加依賴
在 AndroidManifest.xml 添加限權
在 AndroidManifest.xml 注冊Service (MyMqttService為自己寫的服務,下文會講到)
2. 深入分析Android-Handler消息機制
Handler是Android消息機制的上層介面。通過它可以輕松地將一個任務切換到Handler所在的線程中去執行。通常情況下,Handler的使用場景就是 更新UI 。
在子線程中,進行耗時操作,執行完操作後,發送消息,通知主線程更新UI。
Handler消息機制主要包括: MessageQueue 、 Handler 、 Looper 這三大部分,以及 Message 。
從上面的類圖可以看出:
MessageQueue、Handler和Looper三者之間的關系: 每個線程中只能存在一個Looper,Looper是保存在ThreadLocal中的。 主線程(UI線程)已經創建了一個Looper,所以在主線程中不需要再創建Looper,但是在其他線程中需要創建Looper。 每個線程中可以有多個Handler,即一個Looper可以處理來自多個Handler的消息。 Looper中維護一個MessageQueue,來維護消息隊列,消息隊列中的Message可以來自不同的Handler。
在子線程執行完耗時操作,當Handler發送消息時,將會調用 MessageQueue.enqueueMessage ,向消息隊列中添加消息。 當通過 Looper.loop 開啟循環後,會不斷地從消息池中讀取消息,即調用 MessageQueue.next , 然後調用目標Handler(即發送該消息的Handler)的 dispatchMessage 方法傳遞消息, 然後返回到Handler所在線程,目標Handler收到消息,調用 handleMessage 方法,接收消息,處理消息。
從上面可以看出,在子線程中創建Handler之前,要調用 Looper.prepare() 方法,Handler創建後,還要調用 Looper.loop() 方法。而前面我們在主線程創建Handler卻不要這兩個步驟,因為系統幫我們做了。
初始化Looper :
從上可以看出,不能重復創建Looper,每個線程只能創建一個。創建Looper,並保存在 ThreadLocal 。其中ThreadLocal是線程本地存儲區(Thread Local Storage,簡稱TLS),每個線程都有自己的私有的本地存儲區域,不同線程之間彼此不能訪問對方的TLS區域。
開啟Looper
創建Handler :
發送消息 :
post方法:
send方法:
3. Andriod是不是每個線程都有消息隊列
你好
很高興為你解答
答案是:
熟悉Windows編程的朋友可能知道Windows程序是消息驅動的,並且有全局的消息循環系統。而Android應用程序也是消息驅動的,按道 理來說也應該提供消息循環機制。實際上谷歌參考了Windows的消息循環機制,也在Android系統中實現了消息循環機制。Android通過 Looper、Handler來實現消息循環機制,Android消息循環是針對線程的(每個線程都可以有自己的消息隊列和消息循環)。本文深入介紹一下 Android消息處理系統原理。
前面提到Android系統的消息隊列和消息循環都是針對具體線程的,一個線程可以存在(當然也可以不存在)一個消息隊列和一個消息循環 (Looper),特定線程的消息只能分發給本線程,不能進行跨線程,跨進程通訊。但是創建的工作線程默認是沒有消息循環和消息隊列的,如果想讓該線程具 有消息隊列和消息循環,需要在線程中首先調用Looper.prepare()來創建消息隊列,然後調用Looper.loop()進入消息循環。
滿意請採納,謝謝
4. Android的handler機制的原理
Android的handler機制的原理分為非同步通信准備,消息發送,消息循環,消息處理。
1、非同步通信准備
在主線程中創建處理器對象(Looper)、消息隊列對象(Message Queue)和Handler對象。
2、消息入隊
工作線程通過Handler發送消息(Message) 到消息隊列(Message Queue)中。
3、消息循環
消息出隊: Looper循環取出消息隊列(Message Queue) 中的的消息(Message)。
消息分發: Looper將取出的消息 (Message) 發送給創建該消息的處理者(Handler)。
4、消息處理
處理者(Handler) 接收處理器(Looper) 發送過來的消息(Message),根據消息(Message) 進行U操作。
handler的作用
handler是android線程之間的消息機制,主要的作用是將一個任務切換到指定的線程中去執行,(准確的說是切換到構成handler的looper所在的線程中去出處理)android系統中的一個例子就是主線程中的所有操作都是通過主線程中的handler去處理的。
Handler的運行需要底層的 messagequeue和 looper做支撐。
5. Android消息隊列淺析
當面試官問到你消息對列的時候,恭喜你,已經跨過初級,在試探你的中級水平了。
Android的消息循環是參考Windows的消息循環機制來實現的。
消息隊列4件套 Message、MessageQueue、Looper、Handler
1、Message 是消息對列的消息實體類,因為消息隊列中會存放最多10個Message對象。常用屬性 what,是消息體的Tag,用來區分是那個一消息體。
2、 MessageQueue 先進先出」的原則存放消息,將Message對象以鏈表的方式串聯起來。
3、Looper 是MessageQueue的管理者,主線程中是一對一的關系。子線程需要用到消息對列的話就需要經典二人組 。先調用 Looper.prepare()方法,然後再調用Looper.loop();
4、Handler 是封裝和處理Message對象的。
通過源碼可知消息走向如下
handler.sendMessage()-->handler.sendMessageDelayed()-->handler.sendMessageAtTime()-->msg.target = this;queue.enqueueMessage==>把msg添加到消息隊列中