Android 程式碼優化

lostinai發表於2014-04-14

主要介紹Java程式碼中效能優化方式及網路優化,包括快取、非同步、延遲、資料儲存、演算法、JNI、邏輯等優化方式。


1、降低執行時間

這部分包括:快取、資料儲存優化、演算法優化、JNI、邏輯優化、需求優化幾種優化方式。
(1). 快取
快取主要包括物件快取、IO快取、網路快取、DB快取,物件快取能減少記憶體的分配,IO快取減少磁碟的讀寫次數,網路快取減少網路傳輸,DB快取較少Database的訪問次數。
在記憶體、檔案、資料庫、網路的讀寫速度中,記憶體都是最優的,且速度數量級差別,所以儘量將需要頻繁訪問或訪問一次消耗較大的資料儲存在快取中。
 
Android中常使用快取:
a.  執行緒池
b.  Android圖片快取,Android圖片Sdcard快取,資料預取快取
c. 訊息快取
通過handler.obtainMessage複用之前的message,如下:

  1. handler.sendMessage(handler.obtainMessage(0, object));  

d. ListView快取
e. 網路快取
資料庫快取http response,根據http頭資訊中的Cache-Control域確定快取過期時間。
f. 檔案IO快取
使用具有快取策略的輸入流,BufferedInputStream替代InputStream,BufferedReader替代Reader,BufferedReader替代BufferedInputStream.對檔案、網路IO皆適用。
g. layout快取
h. 其他需要頻繁訪問或訪問一次消耗較大的資料快取
 
(2). 資料儲存優化
包括資料型別、資料結構的選擇。
a. 資料型別選擇
字串拼接用StringBuilder代替String,在非併發情況下用StringBuilder代替StringBuffer。如果你對字串的長度有大致瞭解,如100字元左右,可以直接new StringBuilder(128)指定初始大小,減少空間不夠時的再次分配。
64位型別如long double的處理比32位如int慢
使用SoftReference、WeakReference相對正常的強應用來說更有利於系統垃圾回收
final型別儲存在常量區中讀取效率更高
LocalBroadcastManager代替普通BroadcastReceiver,效率和安全性都更高
 
b. 資料結構選擇
常見的資料結構選擇如:
ArrayList和LinkedList的選擇,ArrayList根據index取值更快,LinkedList更佔記憶體、隨機插入刪除更快速、擴容效率更高。一般推薦ArrayList。
ArrayList、HashMap、LinkedHashMap、HashSet的選擇,hash系列資料結構查詢速度更優,ArrayList儲存有序元素,HashMap為鍵值對資料結構,LinkedHashMap可以記住加入次序的hashMap,HashSet不允許重複元素。
HashMap、WeakHashMap選擇,WeakHashMap中元素可在適當時候被系統垃圾回收器自動回收,所以適合在記憶體緊張型中使用。
Collections.synchronizedMap和ConcurrentHashMap的選擇,ConcurrentHashMap為細分鎖,鎖粒度更小,併發效能更優。Collections.synchronizedMap為物件鎖,自己新增函式進行鎖控制更方便。
 
Android也提供了一些效能更優的資料型別,如SparseArray、SparseBooleanArray、SparseIntArray、Pair。
Sparse系列的資料結構是為key為int情況的特殊處理,採用二分查詢及簡單的陣列儲存,加上不需要泛型轉換的開銷,相對Map來說效能更優。不過我不太明白為啥預設的容量大小是10,是做過資料統計嗎,還是說現在的記憶體優化不需要考慮這些東西,寫16會死嗎,還是建議大家根據自己可能的容量設定初始值。


(3). 演算法優化
這個主題比較大,需要具體問題具體分析,儘量不用O(n*n)時間複雜度以上的演算法,必要時候可用空間換時間。
查詢考慮hash和二分,儘量不用遞迴。可以從結構之法 演算法之道或微軟、Google等面試題學習。
 
(4). JNI
Android應用程式大都通過Java開發,需要Dalvik的JIT編譯器將Java位元組碼轉換成原生程式碼執行,而原生程式碼可以直接由裝置管理器直接執行,節省了中間步驟,所以執行速度更快。不過需要注意從Java空間切換到本地空間需要開銷,同時JIT編譯器也能生成優化的原生程式碼,所以糟糕的原生程式碼不一定效能更優。

(5). 邏輯優化
這個不同於演算法,主要是理清程式邏輯,減少不必要的操作。
 
(6). 需求優化
這個就不說了,對於sb的需求可能帶來的效能問題,只能說做為一個合格的程式設計師不能只是執行者,要學會說NO。不過不能拿這種介面敷衍產品經理哦。
 
2、非同步,利用多執行緒提高TPS
充分利用多核Cpu優勢,利用執行緒解決密集型計算、IO、網路等操作。
關於多執行緒可參考:
在Android應用程式中由於系統ANR的限制,將可能造成主執行緒超時操作放入另外的工作執行緒中。在工作執行緒中可以通過handler和主執行緒互動。
 
3、提前或延遲操作,錯開時間段提高TPS
(1) 延遲操作
不在Activity、Service、BroadcastReceiver的生命週期等對響應時間敏感函式中執行耗時操作,可適當delay。
Java中延遲操作可使用ScheduledExecutorService,不推薦使用Timer.schedule;
Android中除了支援ScheduledExecutorService之外,還有一些delay操作,如
handler.postDelayed,handler.postAtTime,handler.sendMessageDelayed,View.postDelayed,AlarmManager定時等。
 
(2) 提前操作
對於第一次呼叫較耗時操作,可統一放到初始化中,將耗時提前。如得到桌布wallpaperManager.getDrawable();
 
4、網路優化
以下是網路優化中一些客戶端和伺服器端需要儘量遵守的準則:
a. 圖片必須快取,最好根據機型做圖片做圖片適配
b. 所有http請求必須新增httptimeout
c. api介面資料以json格式返回,而不是xml或html
d. 根據http頭資訊中的Cache-Control域確定是否快取請求結果。
e. 減少網路請求次數,伺服器端適當做請求合併。
f. 減少重定向次數
g. api介面伺服器端響應時間不超過100ms
google正在做將移動端網頁速度降至1秒的專案,關注中https://developers.google.com/speed/docs/insights/mobile

相關文章