性能優化之Java(Android)代碼優化

性能優化之Java(Android)代碼優化

本文爲Android性能優化的第三篇——Java(Android)代碼優化。主要介紹Java代碼中性能優化方式及網絡優化,包括緩存、異步、延遲、數據存儲、算法、JNI、邏輯等優化方式。(時間倉促,後面還會繼續完善^_*)

 

性能優化專題已完成五部分:

性能優化總綱——性能問題及性能調優方式
性能優化第三篇——Java(Android)代碼優化
性能優化第二篇——佈局優化
性能優化第一篇——數據庫性能優化

性能優化實例 
1、降低執行時間
這部分包括:緩存、數據存儲優化、算法優化、JNI、邏輯優化、需求優化幾種優化方式。
(1). 緩存
緩存主要包括對象緩存、IO緩存、網絡緩存、DB緩存,對象緩存能減少內存的分配,IO緩存減少磁盤的讀寫次數,網絡緩存減少網絡傳輸,DB緩存較少Database的訪問次數。
在內存、文件、數據庫、網絡的讀寫速度中,內存都是最優的,且速度數量級差別,所以儘量將需要頻繁訪問或訪問一次消耗較大的數據存儲在緩存中。

 

Android中常使用緩存:
a.  線程池
b.  Android圖片緩存Android圖片Sdcard緩存數據預取緩存
c. 消息緩存
通過handler.obtainMessage複用之前的message,如下:

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. 開啓gzip壓縮
d. api接口數據以json格式返回,而不是xml或html
e. 根據http頭信息中的Cache-Control及expires域確定是否緩存請求結果。

f. 確定網絡請求的connection是否keep-alive
g. 減少網絡請求次數,服務器端適當做請求合併。
h. 減少重定向次數
i. api接口服務器端響應時間不超過100ms
google正在做將移動端網頁速度降至1秒的項目,關注中https://developers.google.com/speed/docs/insights/mobile


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