Android性能優(yōu)化學(xué)習(xí)
本文為作者原創(chuàng),轉(zhuǎn)載請(qǐng)注明作者和出處
最近公司主抓性能優(yōu)化工作,借此春風(fēng)也學(xué)習(xí)到了許多Android性能優(yōu)化方面的知識(shí)。由于組內(nèi)隊(duì)友的給力荞彼,優(yōu)化的成果也是比較喜人。同時(shí)也學(xué)習(xí)和實(shí)踐了不少知識(shí)待笑,特此記錄鸣皂。
1.性能優(yōu)化分析工具學(xué)習(xí)
工欲善其事,必先利其器暮蹂。在開始代碼優(yōu)化之前寞缝,先得學(xué)會(huì)使用性能分析工具。以下三個(gè)工具都是谷歌官方推出的仰泻,可以幫助我們定位分析問(wèn)題第租,從而優(yōu)化我們的APP。
- System Trace
Systrace是一個(gè)收集和檢測(cè)時(shí)間信息的工具, 它能顯示CPU和時(shí)間被消耗在哪兒了, 每個(gè)進(jìn)程和線程都在其CPU時(shí)間片內(nèi)做了什么事兒. 而且會(huì)指示哪個(gè)地方出了問(wèn)題, 以及給出Fix建議我纪。給出的結(jié)果trace文件是以html形式打開的慎宾,直接用瀏覽器打開查看十分方便丐吓。打開方法:打開DDMS后,連接手機(jī)趟据,點(diǎn)擊手機(jī)上方一排按鈕中的SysTrace按鈕券犁。
打開的效果如下圖:
在代碼中打點(diǎn)方式如下
Trace.beginSection("name");
//要檢測(cè)運(yùn)行時(shí)間的代碼
Trace.endSection();
- Hierarchy Viewer
Hierarchy Viewer提供了一個(gè)可視化的界面來(lái)觀測(cè)布局的層級(jí), 讓我們可以優(yōu)化布局層級(jí), 刪除多余的不必要的View層級(jí), 提升布局速度。另外汹碱,開發(fā)者模式中調(diào)試GPU過(guò)度繪制選項(xiàng)也可以進(jìn)行視圖層級(jí)調(diào)試粘衬。在SDK-> tools目錄下打開hierarchyviewer.bat即可。
效果如下圖:
- TraceView
一個(gè)圖形化的工具, 用來(lái)展示和分析方法的執(zhí)行時(shí)間咳促。也是一款性能優(yōu)化的神器稚新。可以通過(guò)像打log一樣的方式去定位代碼的執(zhí)行時(shí)間跪腹,從而可以準(zhǔn)確定位是哪一段代碼的執(zhí)行消耗了太多時(shí)間褂删。相比SysTrace,功能更強(qiáng)大冲茸,使用起來(lái)也更復(fù)雜屯阀。
2.布局優(yōu)化
布局優(yōu)化相對(duì)比較容易,優(yōu)化可以先從布局來(lái)展開轴术。使用Hierarchy Viewer和開發(fā)者模式中關(guān)于布局繪制的選項(xiàng)难衰,可以查到一些問(wèn)題然后進(jìn)行修改。
布局嵌套過(guò)深 有的時(shí)候?yàn)榱粟s進(jìn)度逗栽,布局設(shè)計(jì)的不是很好盖袭。層級(jí)嵌套過(guò)深的話,深度遍歷各個(gè)節(jié)點(diǎn)會(huì)非常消耗時(shí)間彼宠,這也是布局優(yōu)化余地最大的一個(gè)點(diǎn)了鳄虱。很多過(guò)深的層級(jí)是不必要的。如果布局真的很復(fù)雜兵志,不深度嵌套沒法實(shí)現(xiàn)想要的效果醇蝴。試試最新的約束布局Constraintlayout吧宣肚。沒有使用過(guò)的話想罕,下面這篇官方文檔可以幫助你:
Constraintlayout官方介紹文檔使用合適的布局 三種常見的ViewGroup的繪制速度:FrameLayout > LinerLayout > RelativeLayout。當(dāng)然霉涨,如果用RelativeLayout可以避免布局嵌套的話是值得的按价。可以根據(jù)這些去決定選用什么樣的布局笙瑟。
列表控件優(yōu)化 不論是ListView還是RecycleView都有優(yōu)化點(diǎn)楼镐,一個(gè)是convertView的復(fù)用,一個(gè)是ViewHolder的使用避免重復(fù)遍歷節(jié)點(diǎn)往枷。當(dāng)然這些都是基礎(chǔ)中的基礎(chǔ)了框产。如果發(fā)現(xiàn)項(xiàng)目中的代碼ListView或者RecycleView的使用不規(guī)范的話凄杯,趕緊進(jìn)行修改吧。
使用include標(biāo)簽 在布局文件中秉宿,<include>標(biāo)簽可以指定插入一段布局文件到當(dāng)前布局戒突。這樣的話既提高了布局復(fù)用,也減少了我們的代碼書寫描睦。另外膊存,<merge>標(biāo)簽可以和<include>的標(biāo)簽一起使用從而減少布局層級(jí)。
ViewStub延時(shí)加載 有些布局忱叭,比如網(wǎng)絡(luò)出錯(cuò)的布局隔崎,沒必要在所有時(shí)候都加載出來(lái)。使用ViewStub可以實(shí)現(xiàn)按需加載韵丑。ViewStub本身沒有寬高爵卒,加載起來(lái)幾乎不消耗什么資源。當(dāng)對(duì)他setVisibility(View.VISIBLE)的時(shí)候會(huì)調(diào)用它引用的真實(shí)布局填充到當(dāng)前位置埂息,從而實(shí)現(xiàn)了延時(shí)加載技潘,節(jié)省了正常加載的時(shí)間。
移除Activity默認(rèn)背景 只要我們不需要Activity的默認(rèn)背景千康,就可以移除掉享幽,以減少Activity啟動(dòng)時(shí)的渲染時(shí)間,提升啟動(dòng)效率拾弃。移動(dòng)方法見下:
<style name="MyStyle" parent="AppTheme">
<item name="android:windowNoTitle">true</item>
<item name="android:windowBackground">@null</item>
</style>
3.線程優(yōu)化
線程的創(chuàng)建和銷毀會(huì)帶來(lái)比較大的性能開銷值桩。因此線程優(yōu)化也很有必要。查看項(xiàng)目中是否存在隨意new thread豪椿,線程缺乏管理的情況奔坟。使用AsyncTask或者線程池對(duì)線程進(jìn)行管理,可以提升APP的性能搭盾。另外咳秉,我比較推薦使用Rxjava來(lái)實(shí)現(xiàn)異步操作,既方便又優(yōu)雅鸯隅。
4.內(nèi)存泄露
內(nèi)存泄露會(huì)導(dǎo)致APP占用內(nèi)存過(guò)高澜建,影響效率,嚴(yán)重的話會(huì)導(dǎo)致OOM蝌以。因此如果項(xiàng)目存在內(nèi)存泄露的話要優(yōu)先解決炕舵。查找內(nèi)存泄露可以用LeakCanary等工具,具體怎么解決跟畅,有哪些泄露點(diǎn)咽筋,以后有時(shí)間也寫篇總結(jié)。
5.算法優(yōu)化
毋庸置疑徊件,使用合適的算法處理事務(wù)可以大幅提升APP的性能奸攻。當(dāng)然算法不是我的強(qiáng)項(xiàng)蒜危,也只能給出一些大致的點(diǎn):查詢考慮二分查找節(jié)省時(shí)間,盡量不要使用耗時(shí)的遞歸算法睹耐。必要的時(shí)候可以空間換時(shí)間來(lái)提高APP運(yùn)行效率舰褪。
6.其他優(yōu)化點(diǎn)
異步處理耗時(shí)任務(wù) 在Activity、Fragemnt的onCreate等初始化方法中疏橄,如果執(zhí)行了太耗時(shí)的操作(例如讀取各種數(shù)據(jù))占拍,會(huì)影響頁(yè)面的加載速度,讓用戶覺得APP太慢捎迫。這時(shí)候可以異步處理這些耗時(shí)任務(wù)晃酒,減小應(yīng)用啟動(dòng)的時(shí)候的負(fù)擔(dān)。
替換矢量圖 盡管矢量圖有諸多優(yōu)點(diǎn)窄绒,但矢量圖的繪制是消耗性能的贝次。在應(yīng)用初始化加載等比較影響用戶體驗(yàn)的地方,還是建議使用Bitmap來(lái)代替矢量圖彰导,提高APP開啟效率蛔翅。
正則表達(dá)式 經(jīng)小伙伴用TraceView不斷的打點(diǎn)發(fā)現(xiàn),正則表達(dá)式非常消耗時(shí)間位谋。因此盡管正則表達(dá)式非常優(yōu)雅山析,涉及到性能問(wèn)題的時(shí)候,可以改為其他判斷方式來(lái)提高APP性能掏父。
浮點(diǎn)類型 在Java中浮點(diǎn)類型的運(yùn)算大概比整型數(shù)據(jù)慢兩倍笋轨,因此整型數(shù)據(jù)能解決的問(wèn)題盡量用整型。
減少冗余l(xiāng)og 開發(fā)的時(shí)候用于調(diào)試的log赊淑,在項(xiàng)目上線的時(shí)候沒用的要及時(shí)刪除爵政。當(dāng)然有用的log還是要留下,以便以后分析問(wèn)題陶缺。
刪除無(wú)用資源 沒用用的資源會(huì)增大APK大小钾挟,既然沒有用了,上線的時(shí)候當(dāng)然要及時(shí)刪除饱岸。
Lint代碼檢查 使用Lint等靜態(tài)代碼檢查工具可以幫助我們發(fā)現(xiàn)很多隱藏的問(wèn)題掺出。Lint檢查出來(lái)的問(wèn)題越少,說(shuō)明代碼越規(guī)范伶贰,越不容易出現(xiàn)各種問(wèn)題蛛砰,APP性能自然也會(huì)提升罐栈。
濫用全局廣播 全局廣播也是十分消耗性能的一個(gè)點(diǎn)黍衙。對(duì)于應(yīng)用內(nèi)的通訊,使用接口回調(diào)荠诬,EventBus等手段比起廣播是更好地選擇琅翻。動(dòng)態(tài)注冊(cè)廣播的時(shí)候位仁,也不要忘了廣播的注銷。
7.總結(jié)
可以看到除了工具的使用外方椎,性能優(yōu)化是很考驗(yàn)代碼功底的聂抢。因此想要做好性能優(yōu)化,強(qiáng)化基本功不可少棠众。性能優(yōu)化也是一件相對(duì)枯燥而難度大的工作琳疏。因?yàn)楹芏鄡?yōu)化的努力可能立馬看不到效果,或者說(shuō)優(yōu)化的成果在數(shù)據(jù)上難以體現(xiàn)闸拿。我們?cè)谧鲂阅軆?yōu)化的時(shí)候也遇到果瓶頸空盼,找不到優(yōu)化方向而感到泄氣。但是堅(jiān)持下來(lái)新荤,利用好工具揽趾,從各個(gè)點(diǎn)去優(yōu)化,總會(huì)有撥開云霧見青天的一天苛骨!