編輯:關於Android編程
一、高級優化
上篇主要從初級優化的方式,本篇主要將從程序運行性能的角度出發,分析各種常用方案的不足,並給出對象池技術、基礎數據類型替換法、屏蔽函數計算三種能夠節省資源開銷和處理器時間的優化策略。
目前普遍采用的優化方案有:
· 優化循環,通過重新組織重復的子表達式來提高循環體的運行性能
· 減少使用對象的數量來提高運行性能
· 縮減網絡傳輸數據來縮短等待時間等
本篇學習另外三種性能優化的策略:
1. 采用對象池技術,提高對象的利用率
Java 中創建和釋放對象會占用相當大的資源,采用對象池技術,用來提高對象的利用率
例如:游戲中敵機處理方式:方法一是游戲載入關卡時候,為每架敵機創建一個對象,這種方案中創建對象的資源開銷巨大,因此嚴重影響手機游戲的運行性能。方法二是游戲進程中,動態創建敵機對象,被擊毀以後將對象設置為null並由System.gc() 回收。
游戲性能損耗主要在創建和釋放對象,而不創建對象又無法實現邏輯功能,因此要盡量避免對象的創建和釋放。
解決方案:根據需求先創建一定量的對象,在需要的創建對象的時候從對象池中申請空閒對象,釋放對象時把對象釋放回池中,以有效避免由創建和釋放對象帶來的性能損失
上例中需求是敵機不超過5架,所以可以使用如下代碼:
Enemy[5] enemy = new Enemy[5]; for(int i = 0; i<5;i++){ enemy[i] = new Enemy(); }在類Enemy 李增加標志屬性used 和帶參數的 reset 方法使對象可重置到初始狀態,在載入游戲關卡的時候初始化對象池,在需要創建對象的時候從對象池獲取一個未被使用的對象並使用 reset 方法初始化,需要釋放對象的時候只需將標志位修改以供下次使用。
2. 局部使用基本數據類型代替對象,節省資源開銷
3. 用簡單的數值計算代替復雜的函數計算,節省處理器時間
二、 Android 高效開發
兩個基本原則:不要做不必要做的事情;盡可能的節省內存的使用。
1. 盡可能的避免創建對象。如下優化案例:
· 從原始輸入數據中提取字符串時,試著從原始字符串返回一個子字符串,而不是創建一份副本。你將會創建一個新的字符串對象,但是它和你的原始數據共享數據空間。
· 如果你有一個返回字符串的方法,你應該知道無論如何返回的結果是StringBuffer,改變你的函數的定義和執行,讓函數直接返回而不是通過創建一個臨時的對象。
· 一個 Int 類型數組要比一個 Integer 類型的數組要好,但同樣也可以歸納這樣一個原則,兩個 Int 類型的數組要比一個 (int, int) 對象數組的效率高得多。其他基礎數據類型也是如此。
· 兩個平行的 Foo[] 和 Bar[] 要比一個(Foo,Bar) 對象數組的效率高得多
一般來說,我們應該盡可能地避免創建短期的臨時對象。越少的對象創建意味著越少的垃圾回收,這樣提高你程序的用戶體驗質量。
2. 使用自身方法
當處理字符串的時候,不要猶豫,盡可能多地使用諸如: String.indexOf()、String.lastIndexOf() 這樣對象自身帶有的方法。因為這些方法是用C/C++ 來實現的,比Java 循環來的快10~100 倍
3. 使用虛擬優於使用接口
假設你有一個 HashMap 對象,你可以申明它是一個 HashMap 或者只是一個 Map,如下:
Map myMap1 = new HashMap(); HashMap myMap2 = new HashMap();一般來說明智的做法是使用 Map,因為它允許你改變 Map 接口執行上面的任何東西,。相對於通過具體的引用進行虛擬函數的調用,通過接口引用來調用會花費2倍以上的時間。
4. 使用靜態優於使用虛擬
如果你沒有必要去訪問對象的外部,那麼就使你的方法成為靜態。它會被更快的調用,因為它不需要一個虛擬函數導向表。調用這個方法不會改變對象的狀態。
5. 盡可能避免使用內在的Get,Set 方法
虛方法的調用會產生很多代價,比實例屬性查詢的代價還要多。我們應該在外部調用時使用 Get 和 Set 函數,但是在內部調用時,我們應該直接調用。
6. 緩沖屬性調用
for(int i = 0; i < this.mCount; i++){ dumpItem(this.mItems[i]); }應該這樣寫:
int count = this.mCount; for(int i = 0; i < count; i++){ dumpItem(this.mItems[i]); }一個相似的原則就是:絕不在一個 For 語句中第二次調用一個類的方法。
7. 申明 Final 常量
static String strVal = "100"; static final String strVal = "100";不加 final 編譯器會調用一個類初始化方法
將一個類或者方法申明為“final” 並不會帶來任何執行上的好處,它能夠進行一定的最優化處理。如果編譯器知道一個Get 方法不能被子類重載,那麼它就該把函數設置成 Inline
8. 慎用增強型 For 循環語句
在其他收集器裡面,增強型 for 循環相當於 iterator 的使用。
9. 避免列舉類型
10. 通過內聯類使用包空間
11. 避免浮點類型的使用
嵌入式的處理器通常不支持浮點數的處理,因此所有的 float 和 double 操作都是通過軟件進行的,一些基本的浮點數的操作就需要花費毫秒級的時間。
三、Android UI 優化
1. RelativeLayout 和 LinearLayout 在資源利用上,前者占用更少的資源而達到相同的目的。
RelativeLayout 需要注意的是內部是通過多個View 之間的關系確定的框架,所以當其中一個View 因為某些需要調用 GONE 來完全隱藏掉以後,會影響與其相關聯的Views。 解決方案是使用 alignWithParentIfMissing屬性 來解決類型的問題。
2.
四、圖片優化
1. 圖片壓縮
圖片縮小的操作是刪除部分像素點,小圖放大則要人為地添加一些像素點。圖片放大不總是成倍的。在移植到不同的手機時可以先用菜單畫布界面 getWith() 以及 getHeight() 取得當前手機屏幕的寬度和高度,如果當前圖片不夠滿屏顯示就對圖片進行放大,相反則縮小。也可以自定義屏幕顯示圖片的大小,如在屏幕上顯示多張圖片的縮略圖,使圖片方式的顯示更加豐富。
2. 減少圖片容量
· 將多張圖片集成到一張圖片上。因為省去了多張圖片的文件頭、文件結束數據塊等,而且合並了調色板
· 減少圖片的顏色數
前言羅升陽的《Android系統源代碼情景分析》一書,有關log是如何顯示,那麼真的在代碼中是如何實現的呢?就該問題我想需要細細分析bootloader層的log在fir
在實際的開發中,很多時候還會遇到相對比較復雜的需求,比如產品妹紙或UI妹紙在哪看了個讓人興奮的效果,興致高昂的來找你,看了之後目的很明確,當然就是希望你能給她;在這樣的關
Android中有兩種主要方式使用Service,通過調用Context的startService方法或調用Context的bindService方法,本文只探討純sta
先看效果圖 如何使用 import java.text.DateFormat; import java.text.ParseException; import jav