title: Message創(chuàng)建
date: 2016-11-28 17:57:44
tags: source
categories: android
Message
描述
Message 是Handler數(shù)據(jù)的一個封裝。
Message 對象可以通過new,Message.obtain()或者Handler.obtainMessage()獲取。
創(chuàng)建
直接new一個Message,此時不包含任何的參數(shù)。
-
通過Message.obtain系列方法獲取一個。
Message.obtain(); Message.obtain(Message orig); Message.obtain(Handler h); Message.obtain(Handler h, Runnable callback); Message.obtain(Handler h, int what); Message.obtain(Handler h, int what, Object obj); Message.obtain(Handler h, int what, int arg1, int arg2); Message.obtain(Handler h, int what, int arg1, int arg2, Object obj); -
通過Handler.obtainMessage 系列方法獲取一個
Handler.obtainMessage(); Handler.obtainMessage(int what); Handler.obtainMessage(int what, Object obj); Handler.obtainMessage(int what, int arg1, int arg2); Handler.obtainMessage(int what, int arg1, int arg2, Object obj);
1. 通過Handler創(chuàng)建Message方法時,其實還是調(diào)用到對應(yīng)的Message.obtain方法中。 2. 所有的方法都會執(zhí)行Message.obtain。主要作用是進行Message的回收利用。所以比單獨的new一個Message效率好
我的問題
-
Message對象是如何實現(xiàn)回收利用的?
有五個對象需要關(guān)注:sPoolSync,sPool,m.next,sPoolSize,MAX_POOL_SIZE:
1). sPoolSync只是一個簡單的Object對象,static final 描述,全局看都是通過synchronized去實現(xiàn)同步。 2). 在回收時,next指向當前sPool,sPool指向當前Message??磥磉@兩個參數(shù)是相當于列表的指針 3). 判斷sPoolSize小于MAX_POOL_SIZE。這個應(yīng)該是最大保留的Message對象,最大50個。 4). 每次使用時,當前Message中都有兩個對象,一個指向上一次使用的Message.一個指向當前的可用的Message。 當每次取一個之后,就會把隊列中當前的Message向前移動一格。如果使用不頻繁,那么每次都會使用一個。 當頻繁使用的時候就會使用好多個,最后使用完成又增加好多個Message,這樣完成重用的機制。這里有一個容易出問題,就是你不能直接調(diào)用Message的recycle方法。因為Looper.loop()方法中已經(jīng)主動調(diào)用了這個。
感謝下面大神的博客,不然我也一直想不通為啥我從來沒有調(diào)用過recycle,還懷疑是自己使用錯了呢。
<font color=red>仿照Message實現(xiàn)對象的重用是一個很好的例子,但是要注意形成死循環(huán)。</font>讀讀源碼真好,這個原理知道,但是以前想不到這個辦法,以前能想到的創(chuàng)建一個隊列去處理?。?!
-
在Message中為什么要保留Handler對象?
如果只是單純的通過Message類去看Handler對象的使用。那么在Message中保留Handler對象的第一個作用就是:
//target 就是Handler對象 public void sendToTarget() { target.sendMessage(this); }
第二個作用:(最主要作用)
在Looper的loop循環(huán)中,會根據(jù)每個Message的Handler發(fā)送消息給自己的Handler。
```java
try {
msg.target.dispatchMessage(msg);
} finally {
if (traceTag != 0) {
Trace.traceEnd(traceTag);
}
}
```