vacantcell缓存分析
http://blog.csdn.net/droidpioneer/article/details/6758057?
操作過Android手機的朋友應該對在待機界面拖動圖標的交互效果都有比較深刻的印象,比如說,當把圖標拖動起來,圖標會懸浮并隨著拖動變換位置,當拖動釋放后,圖標會自動的尋找附近合適的空白網(wǎng)格位置。Android在實現(xiàn)這個效果的過程中采用了很多編程技巧,本文著重論述的VacantCell緩存就很具有代表性。
VacantCell緩存主要是對同一種類型對象的緩存機制,這種機制的目的是復用已經(jīng)分配過但已過期的對象,從而避免頻繁的new新的對象。我們知道對象分配是一件比較耗費系統(tǒng)資源的事情,在需要頻繁、大量的分配對象的時候Android平臺很可能出現(xiàn)堆內(nèi)存不足進而導致系統(tǒng)變慢、應用報錯重啟等嚴重問題。用戶在待機界面拖動圖標是很頻繁的事情,而Android的屏幕中空白網(wǎng)格的尋址算法就采用了這種VacantCell緩存來避免頻繁new大量新的對象。
VacantCell類的實現(xiàn)其實很簡單,就不到50行實現(xiàn)代碼:
view plaincopy to clipboard可以看到,VacantCell實際上是一個Java靜態(tài)內(nèi)部類,其外部類CellLayout.java的代碼路徑是\packages\apps\Launcher2\src\com\android\launcher2\CellLayout.java(具體如何下載Android gingerbread Launcher單個模塊的下載方法見博文Android源碼下載——用git clone實現(xiàn)單個目錄下載)。
下面我們具體分析下VacantCell的緩沖機制是如何實現(xiàn)的。
cellX、cellY、spanX、spanY幾個成員是空白網(wǎng)格的縱橫索引號和占據(jù)相應單元網(wǎng)格數(shù),我們這里可以不用關心。
POOL_LIMIT定義了可以緩存的VacantCell的最大值,正如注釋所說,最多可以分配多達523個VacantCell對象,但是對于4X4的屏幕網(wǎng)格定義來說,100個的緩沖數(shù)應該是足夠的了。也就是說,這個100的數(shù)值是一個經(jīng)驗值,我們可以根據(jù)實際情況作靈活修改。
sLock是一個Java Object對象,主要是拿來作同步控制的,我們可以不用關心。
sAcquiredCount是一個非常重要的變量,其實際上就是一個計數(shù)器,實時的統(tǒng)計當前緩存了多少個VacantCell對象值。根據(jù)這個計數(shù)器和POOL_LIMIT可以控制緩存對象不超過POOL_LIMIT的上限。
sRoot和next是緩存VacantCell對象鏈式存儲的兩個關鍵引用,分別表示VacantCell對象鏈表的表頭和特定VacantCell對象鏈接的下一對象的引用。
好了,下面介紹VacantCell緩存的兩個關鍵靜態(tài)方法acquire()和非靜態(tài)方法release()。
當需要VacantCell新對象的時候,Launcher會調(diào)用靜態(tài)內(nèi)部類的VacantCell的靜態(tài)方法acquire()以獲取新的VacantCell對象。請注意,這里獲取新對象不是直接new一個VacantCell對象,而是acquire的。我們看acquire方法的內(nèi)部,當sRoot為null的時候,是直接new VacantCell并直接return的,因為這個時候?qū)嶋H上還沒有緩存可用;當sRoot不為null,這意味著已經(jīng)有緩存的VacantCell對象了,那么直接從鏈表中取出sRoot指向的對象,并將sRoot所在對象指向的next作為新的表頭sRoot,同時把sAcquiredCount計數(shù)減1。這實際上是一種典型的從鏈表中刪除表頭的操作,相信熟悉數(shù)據(jù)結(jié)構(gòu)的朋友對此都不會陌生。
如果說acquire()方法提供的是如何利用VacantCell鏈式緩存,那么release()方法解決的就是如何構(gòu)建VacantCell鏈式緩存的問題。我們看到,只有sAcquiredCount < POOL_LIMIT的前提下才會將VacantCell對象加入鏈式緩存。將當前VacantCell對象加入鏈式存儲也很簡單,將當前VacantCell對象的next指向原來的表頭,將靜態(tài)sRoot應用指向當前對象,同時sAcquiredCount加1。也就是說,這個操作其實就是把當前VacantCell對象插入VacantCell鏈表的表頭。
那么如何使用這個VacantCell對象緩存呢?第一,當需要新的VacantCell對象的時候,通過調(diào)用VacantCell的靜態(tài)方法acquire()來獲取對象,而不是直接new VacantCell對象;第二,當一個VacantCell對象已經(jīng)過期,不再需要的時候,調(diào)用該對象的release()方法將這個不再需要的對象加入緩存。
需要指出的是,如果直接new VacantCell對象也不會有直接的問題,只不過這意味著沒有采用VacantCell緩存機制;如果一個對象不需要時不顯示調(diào)用release()方法也不會有直接的問題,這意味著這個對象不會加入進VacantCell緩存鏈表,當沒有鏈表各節(jié)點對象的引用關聯(lián),這個對象最終將被Android的Dalvik虛擬機當做垃圾自動回收。
本文詳細分析了Android Launcher模塊VacantCell緩存的實現(xiàn)原理,當我們需要頻繁構(gòu)造、釋放大量的相同類型的Java對象的時候,我們考慮采用類似的緩存機制,這在某些場合下能有效的解決頻繁分配對象導致的內(nèi)存不足的問題。
轉(zhuǎn)載于:https://www.cnblogs.com/greywolf/archive/2012/12/24/2831290.html
總結(jié)
以上是生活随笔為你收集整理的vacantcell缓存分析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JScript 和 VBscript访问
- 下一篇: KVM安装Win系列虚拟机学习笔记