當前位置:首頁 » 安卓系統 » androidmessage

androidmessage

發布時間: 2023-02-02 03:32:58

A. android這樣創建Message可以減少內存開銷

我們一般創建message是這么創建的

Message msg = new Message();

但是這樣創建message可以減少內存開銷

Message msg = handler.obtainMessage();

為什麼會這樣呢?我們來看看源碼,關鍵源碼如下:

//普通的實例化方法

public Message(){}

//obtainMessages實例化方法

public final Message obtainMessage(){

      return Message.obtain(this);

}

public static Message obtain(Handler h){

Message m=obtain();

m.target=h;

return m;

}

public static Message obtain(){

synchronized(sPoolSync){

Message m=sPool;

sPool=m.next;

m.next=null;

sPoolSize--;

return m;

}

return new Message();

}

總結:

上面源碼中說得很明白:從整個Messge池中返回一個新的Message實例,在許多情況下使用它,因為它能避免分配新的對象

如果是這人的話,那麼通過調用obtainMessage方法獲取Message對象就能避免創建對象,從而減少內存的開銷了。

B. 詳解Android消息機制之Message

在分析Message這個類之前,有必要先看看它的類注釋其中有這么一段話:

從這段話得知,盡管Message本身的構造方式是公共的,但實現Message對象的最好方法確實是通過Message.obtain()函數返回,或者通過Handler.obtainMessage()方法,查看其最終還是調用了obtain函數。

如果使用new來實現我們初步的推測,應該是會構建大量的Message對象,對內存有一定的影響。
在這還是先看一下谷歌給這個函數的注釋:

從obtain函數的注釋中也能看出其作用就是用避免大量的構建Message對象,但它是究竟是如何處理的呢?帶著疑問查看obtain函數:

實現很簡單:

但看到這里還是很模糊,雖然sPool看上去像一個消息池,但再仔細看居然是一個Message對象,這樣真的就能避免多次構建Message對象嗎?繼續看會發現一個next欄位,再看它的注釋 sometimes we store linked lists of these things ,Message的消息池原來是一個鏈表,如下圖所示 。

每一個Message 對象通過next指向下一個Message(最後一個Message的next為null)形成一個鏈表,Message對象就成了一個可用的Message池。

到這終於知道Message對象原來是從鏈表中獲取的,但還有一個疑問:Message對象是什麼時候放入鏈表中的呢?從obtain函數並沒有看見存儲Message的操作。這時候又要回到文章開頭的那段類注釋的最後一句話: which will pull them from a pool of recycled objects。
消息池是一些回收的對象,也就是說Message對象是在回收的時候將其添加到鏈表中的。通過查看在Message中有個recycle方法:

在recycleUnchecked函數中會先清空該消息的各個欄位,並且把flags設置為FLGA_IN_USE,表明該消息已經被使用了。然後判斷是否要將消息回收到消息池中,如果池的大小小於MAX_POOL_SIZE,就將自身添加到鏈表的表頭,sPoolSize++。
例如最開始的開始的時候鏈表中沒有任何消息,將第一個Message對象添加到表中,此時的sPool為空,因此next也為空,sPool又指向this,這時sPool就指向當前這個被回收的Message對象,sPoolSize加1。我們把這個Message命名為m1,這時的鏈表應該如下:

如果再次插入一個名為m2的Message,那麼m2將被插入表頭,sPool指向m2,這時sPool的鏈表中結構如下:

對象池默認的大小為50,如果池的大小小於50,被回收的消息將會被插入到鏈表頭部。

如果池中有元素,這時候再調用obtain函數時,實際上是就獲取鏈表中表頭的元素,也就是sPool。再把sPool指針往後移動一個。在obtain漢中,首先會聲明一個Message對象m,並且讓m指向sPool.sPool實際上指向了m2,因此m實際上指向的也是m2,這里相當於保持了m2這個元素。下一步是sPool指向m2的下一個元素,也就是m1。sPool也完成後移之後此時把m.next置空,也就相當於m2.next變成了null。最後就是m指向了m2元素,m2的next為空,sPool從原來的表頭m2指向了下一個元素m1,最後將對象的元素減1,這樣m2就順利的脫離了消息池隊伍,就返回給了調用obtain函數的。

C. android,,message和messenger的區別是什麼

一、概述
說到Android進程間通信,大家肯定能想到的是編寫aidl文件,然後通過aapt生成的類方便的完成服務端,以及客戶端代碼的編寫。如果你對這個過程不熟悉,可以查看Android aidl Binder框架淺析;
當然今天要說的通信方式肯定不是通過編寫aidl文件的方式,那麼有請今天的主角:Messenger。ok,這是什麼樣的一個類呢?我們看下注釋
This allows for the implementation of message-based communication across processes
允許實現基於消息的進程間通信的方式。
那麼,什麼叫基於消息的進程間通信方式呢?看個圖理解下:

可以看到,我們可以在客戶端發送一個Message給服務端,在服務端的handler中會接收到客戶端的消息,然後進行對應的處理,處理完成後,再將結果等數據封裝成Message,發送給客戶端,客戶端的handler中會接收到處理的結果。
這樣的進程間通信是不是很爽呢?
基於Message,相信大家都很熟悉
支持回調的方式,也就是服務端處理完成長任務可以和客戶端交互
不需要編寫aidl文件
此外,還支持,記錄客戶端對象的Messenger,然後可以實現一對多的通信;甚至作為一個轉接處,任意兩個進程都能通過服務端進行通信,這個後面再說。
看到這,有沒有一些的小激動,我們可以不寫aidl文件,方便的實現進程間通信了,是不是又可以裝一下了。哈,下面看個簡單的例子。

熱點內容
編程畫櫻花 發布:2024-03-29 02:11:24 瀏覽:472
騰訊雲伺服器1mb老掉線 發布:2024-03-29 01:56:11 瀏覽:214
執行sql語句的存儲過程 發布:2024-03-29 01:52:37 瀏覽:696
婚紗攝影腳本 發布:2024-03-29 01:47:40 瀏覽:900
我的世界伺服器咋開外掛 發布:2024-03-29 01:07:45 瀏覽:455
sql寫報表 發布:2024-03-29 01:03:23 瀏覽:305
家用伺服器怎麼選 發布:2024-03-29 00:49:18 瀏覽:401
Ap6510dn如何配置 發布:2024-03-29 00:38:47 瀏覽:333
安卓和蘋果哪個更佔用內存 發布:2024-03-29 00:37:02 瀏覽:424
編譯錯誤算bug嗎 發布:2024-03-29 00:23:03 瀏覽:34