Android開發經驗小節2:循環利用你的小對象

在上一篇中提出的原則都是爲了避免創建不必要的對象。對於佔用資源較多的對象,可以在程序初始化中創建,並一直使用,比如圖片資源。對於一些不變的對象,如字符串、常數,可以採用靜態常量的辦法。但我們開發過程中還會遇到另一種情況,有些對象雖然佔用資源少,但使用頻率高(比如記錄屏幕點位置座標的對象),對於這種情況應該如何處理呢?

這個問題其實比較複雜,要具體情況具體分析,但還是有一些規律可循。

原則1:建立對象池循環利用小對象

例如如下類:

 

1 public class TestPoint 2 { 3 public int mX; 4 public int mY; 5 public TestPoint(int x,int y) 6 { 7 set(x,y); 8 } 9 10 public void set(int x,int y) 11 { 12 mX=x; 13 mY=y; 14 } 15 }

 

使用時:

 

 

public void test() { for(int i=0;i<10000;i++) { TestPoint p=new TestPoint(i,i); 。。。 } }

 

通過分析,以上代碼會創建10000個TestPoint新對象,這當然是不合理的,可以用如下辦法優化:

 

 

1 public class TestPoint 2 { 3 public int mX; 4 public int mY; 5 public TestPoint(int x,int y) 6 { 7 set(x,y); 8 } 9 10 public void set(int x,int y) 11 { 12 mX=x; 13 mY=y; 14 } 15 16 17 /** 18 * 對象池 19 */ 20 private static ArrayList<TestPoint> sPoints=null; 21 22 /** 23 * 從對象池中獲取一個對象,如果空池則創建新對象,並初始化 24 * @param x 橫座標 25 * @param y 縱座標 26 * @return 對象 27 */ 28 public static TestPoint popPoint(int x,int y) 29 { 30 TestPoint p=null; 31 if(sPoints!=null && sPoints.size()>0) 32 { 33 p=sPoints.remove(0); 34 p.set(x, y); 35 } 36 else 37 { 38 p=new TestPoint(x,y); 39 } 40 return p; 41 } 42 43 /** 44 * 向對象池歸還一個對象,如果空池則先創建池 45 * @param p 要歸還的對象 46 */ 47 public static void pushPoint(TestPoint p) 48 { 49 if(sPoints==null) 50 { 51 sPoints=new ArrayList<TestPoint> (); 52 } 53 54 sPoints.add(p); 55 } 56 57 }

 

在使用時:

 

 

public void test2() { for(int i=0;i<10000;i++) { TestPoint p=TestPoint.popPoint(i, i); //獲取對象 。。。 TestPoint.pushPoint(p); //歸還對象 } }

 

這樣,由於使用過的對象歸還給了對象池,當需要時優先從池中獲取對象,實際創建對象的次數將明顯下降。

 

原則2:給你的對象池設一個上限

前面的代碼也有侷限性,例如如果程序的邏輯造成其對象獲取峯值較高,池中的對象將或很多,當程序對象獲取需求減少時,池中的對象就成爲了佔用內存的累贅了。一個可行的辦法是,爲對象池中對象數設定一個上限,當歸還對象時發現池中對象已經達到這個上限了,就不再將其放入池中。只要這個上限設定合理,池內存佔用和GC釋放內存壓力可以找到一個較好的平衡點。

原則3:保護好你的對象池

這裏需要強調的是,對於多線程共用的對象池,應該對所有訪問對象池的靜態方法進行嚴格的線程保護,因爲ArrayList的操作還是比較費時且多線程共同對其訪問是是有線程衝突的。

 

小結:

對象池的使用可以對頻繁使用的小對象進行有效的循環利用,如果運用合理,可以極大地提升程序的運行效率和降低程序的資源佔用。但請相信,沒有普遍適用的最優方案,必須具體問題具體分析。

 

作者:汪峯 www.otlive.cn

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章