Android開發(fā)優(yōu)化技巧

1.布局優(yōu)化
為什么?
Android系統(tǒng)每個16ms發(fā)出VSYNC信號,觸發(fā)對UI的渲染,要想達到界面流暢,必須實現(xiàn)60fps,也就意味著大多數(shù)的操作必須在16ms完成.
除了上面界面過于復(fù)雜導(dǎo)致渲染不能及時完成之外,還存在過度繪制問題.所謂過度繪制就是某個像素在同一幀的時間內(nèi)被繪制多次.在多層次的UI界面中,如果不可見的UI也在進行繪制,那么這些重合區(qū)域的像素就會被繪制多次,從而浪費大量的CPU和GPU資源.過度繪制也發(fā)生在背景重疊的情況下,比如Layout中有自己的背景,同時子View中又有自己的背景.
如何檢測?
使用HierarchyViewer來查找Activity中的布局是否過于復(fù)雜
在開發(fā)者選項中打開Show GPU Overdraw選項進行觀察是否存在過度繪制
在開發(fā)者選項中選擇Profile GPU Rendering,選中On screen as bar
使用TraceView來觀察CPU執(zhí)行情況

如何優(yōu)化?
減少布局的層級,合理的使用include,merge,ViewStub
自定義組件的onDraw()中避免大量創(chuàng)建臨時對象,比如String,以免頻繁觸發(fā)GC
自定義組件的onDraw()中,考慮使用canvas.clipRect()繪制需要被繪制的區(qū)域
對像ListView這樣的組件容器,考慮使用convertView,使用ViewHolder,
考慮使用性能更高的組件,比如推薦使用RecycleView來代替ListView,使用staticlayout來實現(xiàn)自動換行

2.內(nèi)存優(yōu)化
為什么?
資源總是有限的,內(nèi)存同樣也是一種資源.在Android當中,過度的/不恰當占用內(nèi)存資源,會導(dǎo)致應(yīng)用頻繁被殺死,最終也會影響用戶的整體體驗.任何一名開發(fā)者,都應(yīng)該將節(jié)省內(nèi)存牢記心中.
如何檢測?
使用LeakCanary
使用MAT分析Java堆
使用Android Device Monitor中的Application Tracker追蹤內(nèi)存分配信息
Android Studio中的Android Monitor,選擇其中的Memory

如何優(yōu)化?
主動的釋放內(nèi)存,在onLowMemory()和onTrimMemory()中適當?shù)尼尫艃?nèi)存

避免內(nèi)存泄漏和內(nèi)存溢出

在使用Bitmap的時候,考慮對其進行壓縮,使用緩存或者改變顏色模式,比如android默認的顏色格式是ARGB_8888,在要求不高的情況下可以采用RGB__565,這樣每個像素占用的內(nèi)存就可懂4byte到2byte.

減少幀動畫的使用,如果需要,通過SurfaceView實現(xiàn)

使用更輕量級的數(shù)據(jù)結(jié)構(gòu),比如ArrayMap/SparseArray

合理的使用相關(guān)組件,比如Service和Webview,在不需要的時候主動結(jié)束其生命周期

合理的使用多進程,比如像音樂播放器類,可以分為主進程和播放進程

使用異步隊列時考慮有界隊列

如果你能明確知道HashMap的大小,那就再初始化時為其制定容量
?

3.電量優(yōu)化
為什么?
電量是移動設(shè)備非常寶貴的資源,作為一名開發(fā)者,有必要為用戶著想,減少電量的消耗.調(diào)查顯示通常只有30%左右的電量是被程序核心的功能所消耗,比如界面渲染,剩下的70%則是被上報數(shù)據(jù),位置更新,后臺通知所消耗.
如何檢測?
手機選項中通過查看APP的電量消耗的統(tǒng)計數(shù)據(jù)
使用Battery Historian Tool來查看詳細的電量消耗

如何優(yōu)化?
減少喚醒屏幕的次數(shù)與持續(xù)的時間,正確的使用WakeLock.
延遲非必須的操作到充電狀態(tài)時,比如日志上報完全可以在夜間充電時完成,這點可以結(jié)合JobScheduler使用
使用傳感器采集數(shù)據(jù)時,一旦不需要記得取消注冊.
減少網(wǎng)絡(luò)通信,合并通信.
合理使用定位功能,減少位置更新頻率以及根據(jù)實際情況使用不同精度的定位需求

4.網(wǎng)絡(luò)優(yōu)化
為什么?
現(xiàn)在App幾乎都需要聯(lián)網(wǎng)操作,做好網(wǎng)絡(luò)優(yōu)化一方面可以提高體驗,另一方面可以減少流量和電量的損耗.另外,無論是對用戶還是網(wǎng)絡(luò)服務(wù)提供者,網(wǎng)絡(luò)同樣是一種資源,任何開發(fā)者都不應(yīng)該假設(shè)網(wǎng)絡(luò)資源是無限制的.
如何檢測?
使用Android Studio里的Network Traffic Tools來查看網(wǎng)絡(luò)請求
使用Android Studio中的Monitor
使用Fidder或者Charles等抓包工具分析網(wǎng)絡(luò)數(shù)據(jù)包

如何優(yōu)化?
有必要的時候務(wù)必做好緩存,無論是圖片還是普通的數(shù)據(jù),使用LruCache和DiskLruCache構(gòu)建自己的緩存系統(tǒng),并根據(jù)實際場景設(shè)計緩存策略
避免過度的網(wǎng)絡(luò)同步,合并相關(guān)的網(wǎng)絡(luò)請求
根據(jù)實際場景確定請求策略,避免使用固定的間隔頻率來進行網(wǎng)絡(luò)操作.比如連接WiFi并充電的情況下請求頻率可以高,第一次網(wǎng)絡(luò)請求失敗后可以使用雙倍的時間間隔來進行下一次
減少數(shù)據(jù)傳輸量,對傳輸?shù)臄?shù)據(jù)做壓縮.如果傳輸?shù)氖菆D片,需要選擇合適的圖片格式以及根據(jù)顯示大小請求合適規(guī)格的圖片.對于普通數(shù)據(jù),可以考慮使用ProtocalBuffers來減小傳輸數(shù)據(jù)的大小.
某些情況下可以采用IP直連,一方面可以減少DNS解析時間,另一方面可以防止域名劫持

5.啟動優(yōu)化
為什么?
啟動優(yōu)化看起來并不是那么必要,但從心理學角度而言,越快的啟動速度往往給用戶以性能好,高效可靠的心理暗示,這就很容易讓用戶對其產(chǎn)生好感,為你后面打動用戶留下了余地.
如何檢測?
使用Method Tracing
使用Systrace,比如在onCreate中添加trace.beginSection()和trace.endSection()
使用adb shell am start -W [packageName]/[packageName.MainActivity]
測量冷啟動時間

如何優(yōu)化?
Activity的onCreate()中減少復(fù)雜和耗時的操作
Application的onCreate(),attachBaseContext()中同樣減少復(fù)雜和耗時的操作,但是對于很多App在此處會執(zhí)行大量組件和服務(wù)的初始化操作,如果可能考慮并行初始化
提供自定義啟動窗口,比如將一張圖片通過設(shè)置主題的方式顯示為啟動窗口.
優(yōu)化布局

6.體積優(yōu)化
為什么?
對用戶而言,無論是用戶空間還是網(wǎng)絡(luò),亦或是時間,都是資源.體積優(yōu)化就是為用戶節(jié)省資源的重要一環(huán).如果你現(xiàn)在做的是SDK類產(chǎn)品,那么體積優(yōu)化同樣重要.
如何檢測?
使用Android Lint檢查沒有使用的資源

如何優(yōu)化?
減少不必要的依賴庫/Jar,在滿足需求的前提下優(yōu)先選擇體積小的.
使用Proguard工具進行代碼瘦身,優(yōu)化,混淆
減少so文件的數(shù)量,根據(jù)實際情況提供so文件
使用Gradle中的shrinkResource來將無用的代碼和資源排除在APK安裝包之外
減少圖片資源的大小,考慮圖片壓縮或者使用Vertor Drawable替代png/jpeg
有選擇的提供對應(yīng)分辨率的圖片資源
復(fù)用已經(jīng)存在的圖片,多用通過代碼對已有圖片進行變換的方式實現(xiàn)復(fù)用
使用插件化技術(shù)(如果項目簡單就不要使用)

7.性能優(yōu)化
能發(fā)揮出100%的能力就不要只發(fā)揮其中的50%,這對應(yīng)用而言并非壞事.同樣的價格賣給用戶兩輛車,我想大多數(shù)人會選擇性能更好的.
如何檢測?
使用Lint執(zhí)行靜態(tài)分析,在Android Studio的Analysis->Inspect Code
在開發(fā)者選項中開啟StrictMode或者在代碼中開啟
代碼Review

如何優(yōu)化?
任務(wù)并行化,對可能的任務(wù)進行并行操作,多借助線程池而非直接使用線程
如何需要序列化數(shù)據(jù),優(yōu)先考慮Android自身提供的而非Java提供的Serializable
選擇合適的數(shù)據(jù)結(jié)構(gòu),明確List/Set/Map/Stack操作的復(fù)雜度
使用Android提供更高效的容器,比如使用ArrayMap來代替HashMap,此外還是有SparseBoolMap,SparseIntMap,SparseLongMap
使用靜態(tài)常量代替Enum類型,可以減少至少兩倍的內(nèi)存消耗
使用對象池技術(shù),比如提供想String一樣的對象池
使用緩存技術(shù)
字符串拼接操作有限使用StringBuilder
對相關(guān)的算法和邏輯進行優(yōu)化,減少不必要的流程
采用JNI,對計算量較大的邏輯將其協(xié)程so文件,如圖片處理

業(yè)務(wù)優(yōu)化
除了上述比較通用的優(yōu)化方案之外,也應(yīng)該花點時間放在業(yè)務(wù)優(yōu)化上.很多時候,迫于時間壓迫,當前實現(xiàn)業(yè)務(wù)的方案并非最優(yōu).比如為了支持多張圖片上傳,很多人直接使用串行操作,盡管這樣做容易實現(xiàn),但是卻并非最佳.
由于每個產(chǎn)品的業(yè)務(wù)并不相同,也就很難有通用的優(yōu)化方案,這里又兩個目標值得思考:
如果有可能,串行業(yè)務(wù)并行化
如果有可能,簡化業(yè)務(wù)流程.將一大象關(guān)進冰箱的方法就是打開冰箱,將大象放進去,最后關(guān)閉冰箱.

之所以把業(yè)務(wù)優(yōu)化放在最后的根本原因是業(yè)務(wù)優(yōu)化的風險較高,需要團隊的整體配合來完成.
Android中圖片有四種顏色格式
默認的是ARGB_8888,其中ARGB分別代表的是透明度,紅色,綠色,藍色,每個值分別用8位來記錄,也就是一個像素會占用4byte,共32位.
而ARGB_4444和以上很類似,但是每個值分別用4位來記錄,也就是一個像素會占用2byte,共16位.
RGB_565則分別用5位,6位,5位來記錄每個值,不存在透明度,每個像素會占用2byte,共16位.
ALPHA_8:該像素只保存透明度,會占用1byte,共8位.
在實際應(yīng)用中而言,值推薦使用ARGB_8888以及RGB_565,如果你不需要透明度,那么就選擇RGB_565,可以減少一半的內(nèi)存占用

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 178,716評論 25 709
  • 2015新年伊始,Google發(fā)布了關(guān)于Android性能優(yōu)化典范的專題,一共16個短視頻,每個3-5分鐘,幫助開...
    huldaZhang閱讀 517評論 0 2
  • 我在天日之下回頭細看,見跑得快的不一定奪標,勇士不一定戰(zhàn)勝,有智慧的不一定得糧,有悟性的不一定致富,有知識的不一定...
    艾羗閱讀 308評論 0 1
  • 正所謂“南有西雙版納,北有莫爾道嘎”。莫爾道嘎國家森林公園不僅植物資源豐富,而且更有各種野生動物出沒。但是,想要玩...
    Poepoepets閱讀 1,100評論 0 1
  • 孩子的教育問題始終縈繞在父母的心頭,尤其是現(xiàn)在社會壓力這么大、競爭如此激烈的情況下,仿佛如一座大山一樣時刻屹立在父...
    在自我提升的路上閱讀 308評論 0 2

友情鏈接更多精彩內(nèi)容