在用Handler時,我們使用Message對象時,google不推薦我們通過new Message()來構造一個Message對象,因為Message我們會頻繁的使用,不斷的new,導致記憶體片段,效率不高。Google推薦我們通過obtain()方法構造,為什麼了?obtain()內部是怎麼實現構造Message從而避免頻繁的new而造成的浪費?
首先我們看看obtain()函數:
(sPool != Message m = sPool = m.next = sPoolSize-- }
其他重載的obtain()函數裡面都是調用了obtain(),所以只需要搞清楚這一個就成了。
首先判斷sPool != null,這兒sPool是Message的一個靜態內部對象:
private static Message sPool;
如果我們首次調用sPool肯定是null了,那麼該函數也就直接執行 return new Message()了。執行完sPool仍然是null,那麼sPool在那初始化了?我們看到其在recycle()中初始化。
(sPoolSize < next = sPool = sPoolSize++ }
該函數被調用的地方很多,但主要是在Looper.loop()中,這兒實現了回收,開始時sPoolSize小於MAX_POOL_SIZE(該值為10),那麼每調用一次recycle(),sPool,next就會被賦值,sPoolSize++,直到sPoolSize = MAX_POOL_SIZE。在這兒sPoolSize++的過程中,sPoll指向調用者對象,保留該對象的引用,next指向前一個對象的引用,注意,這兒next是Message的內部屬性成員,不是static的,所以這樣下來就形成了一個單向鏈表,每個節點是調用了recycle()方法的Message對象,該鏈表的最大長度是MAX_POOL_SIZE。
我們回過頭來再看obtain(),當sPool != null時,m = sPool,其作為傳回值,然後給sPool重新賦值:sPool = m.next,然後m.next = null,sPoolSize--。這個操作其實就是刪除鏈表的最後節點並返回的操作。由此可見原先new的Message對象在這兒都給返回重新使用,實現了重複利用。
Handler中的訊息佇列其實也就是一個Message對象,也就是說訊息對寫並不是MessageQueue來維護,而是由Message自己來實現的。