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

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

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

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

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

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

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

減少幀動(dòng)畫(huà)的使用,如果需要,通過(guò)SurfaceView實(shí)現(xiàn)

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

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

合理的使用多進(jìn)程,比如像音樂(lè)播放器類(lèi),可以分為主進(jìn)程和播放進(jìn)程

使用異步隊(duì)列時(shí)考慮有界隊(duì)列

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

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

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

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

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

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

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

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

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

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

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

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

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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末咬崔,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子虹菲,更是在濱河造成了極大的恐慌摊聋,老刑警劉巖粮彤,帶你破解...
    沈念sama閱讀 206,214評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡或颊,警方通過(guò)查閱死者的電腦和手機(jī)霞掺,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)谊路,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人菩彬,你說(shuō)我怎么就攤上這事缠劝。” “怎么了骗灶?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,543評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵剩彬,是天一觀(guān)的道長(zhǎng)。 經(jīng)常有香客問(wèn)我矿卑,道長(zhǎng)喉恋,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,221評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮轻黑,結(jié)果婚禮上糊肤,老公的妹妹穿的比我還像新娘。我一直安慰自己氓鄙,他們只是感情好馆揉,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著抖拦,像睡著了一般升酣。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上态罪,一...
    開(kāi)封第一講書(shū)人閱讀 49,007評(píng)論 1 284
  • 那天噩茄,我揣著相機(jī)與錄音,去河邊找鬼复颈。 笑死绩聘,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的耗啦。 我是一名探鬼主播凿菩,決...
    沈念sama閱讀 38,313評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼帜讲!你這毒婦竟也來(lái)了衅谷?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 36,956評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤似将,失蹤者是張志新(化名)和其女友劉穎会喝,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體玩郊,經(jīng)...
    沈念sama閱讀 43,441評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡肢执,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評(píng)論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了译红。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片预茄。...
    茶點(diǎn)故事閱讀 38,018評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖侦厚,靈堂內(nèi)的尸體忽然破棺而出耻陕,到底是詐尸還是另有隱情,我是刑警寧澤刨沦,帶...
    沈念sama閱讀 33,685評(píng)論 4 322
  • 正文 年R本政府宣布诗宣,位于F島的核電站,受9級(jí)特大地震影響想诅,放射性物質(zhì)發(fā)生泄漏召庞。R本人自食惡果不足惜岛心,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望篮灼。 院中可真熱鬧忘古,春花似錦、人聲如沸诅诱。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,240評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)娘荡。三九已至干旁,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間炮沐,已是汗流浹背争群。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,464評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留央拖,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,467評(píng)論 2 352
  • 正文 我出身青樓鹉戚,卻偏偏與公主長(zhǎng)得像鲜戒,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子抹凳,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,500評(píng)論 25 707
  • 2015新年伊始遏餐,Google發(fā)布了關(guān)于A(yíng)ndroid性能優(yōu)化典范的專(zhuān)題,一共16個(gè)短視頻赢底,每個(gè)3-5分鐘失都,幫助開(kāi)...
    huldaZhang閱讀 475評(píng)論 0 2
  • 我在天日之下回頭細(xì)看,見(jiàn)跑得快的不一定奪標(biāo)幸冻,勇士不一定戰(zhàn)勝粹庞,有智慧的不一定得糧,有悟性的不一定致富洽损,有知識(shí)的不一定...
    艾羗閱讀 280評(píng)論 0 1
  • 正所謂“南有西雙版納庞溜,北有莫爾道嘎”。莫爾道嘎國(guó)家森林公園不僅植物資源豐富碑定,而且更有各種野生動(dòng)物出沒(méi)流码。但是,想要玩...
    Poepoepets閱讀 894評(píng)論 0 1
  • 孩子的教育問(wèn)題始終縈繞在父母的心頭,尤其是現(xiàn)在社會(huì)壓力這么大碘赖、競(jìng)爭(zhēng)如此激烈的情況下驾荣,仿佛如一座大山一樣時(shí)刻屹立在父...
    在自我提升的路上閱讀 248評(píng)論 0 2