Android性能優(yōu)化

優(yōu)化角度


RAM方面

  • 內(nèi)存泄露優(yōu)化
  • 避免OOM
  • APP啟動(dòng)優(yōu)化
  • 線程優(yōu)化

Res方面

  • apk瘦身
  • 布局優(yōu)化
  • 繪制優(yōu)化
  • ListView和Bitmap優(yōu)化

其他

  • ANR分析
  • 電量優(yōu)化
  • 性能優(yōu)化工具

內(nèi)存泄露優(yōu)化

  • 單例模式的持有;
  • 靜態(tài)對(duì)象的持有
  • 屬性動(dòng)畫不被cancel呆细,其持有view型宝,view又持有activity導(dǎo)致內(nèi)存泄露。
  • 非靜態(tài)內(nèi)部類會(huì)持有外部類的引用絮爷,如果非靜態(tài)內(nèi)部類的實(shí)例是靜態(tài)的趴酣,或者在執(zhí)行耗時(shí)操作,就會(huì)長期的維持著外部類的引用
  • 以匿名內(nèi)部類構(gòu)建的AsyncTask和新線程會(huì)隱式地帶有一個(gè)對(duì)外的引用坑夯,如果在activity結(jié)束時(shí)候沒有執(zhí)行完成岖寞,會(huì)造成內(nèi)存泄露,建議使用靜態(tài)內(nèi)部類柜蜈,在Activity銷毀時(shí)候也應(yīng)該取消相應(yīng)的任務(wù)AsyncTask::cancel()仗谆,避免任務(wù)在后臺(tái)執(zhí)行浪費(fèi)資源
  • Context導(dǎo)致內(nèi)存泄漏
    根據(jù)場景確定使用Activity的Context還是Application的Context,因?yàn)槎呱芷诓煌瑢?duì)于不必須使用Activity的Context的場景(Dialog),一律采用Application的Context,單例模式是最常見的發(fā)生此泄漏的場景淑履,比如傳入一個(gè)Activity的Context被靜態(tài)類引用隶垮,導(dǎo)致無法回收
  • 靜態(tài)View導(dǎo)致泄漏
    使用靜態(tài)View可以避免每次啟動(dòng)Activity都去讀取并渲染View,但是靜態(tài)View會(huì)持有Activity的引用秘噪,導(dǎo)致無法回收狸吞,解決辦法是在Activity銷毀的時(shí)候?qū)㈧o態(tài)View設(shè)置為null(View一旦被加載到界面中將會(huì)持有一個(gè)Context對(duì)象的引用,在這個(gè)例子中,這個(gè)context對(duì)象是我們的Activity蹋偏,聲明一個(gè)靜態(tài)變量引用這個(gè)View便斥,也就引用了activity)
  • BraodcastReceiver,ContentObserver威始,F(xiàn)ile椭住,Cursor,Stream字逗,Bitmap、系統(tǒng)服務(wù)等資源及時(shí)關(guān)閉宅广,它們內(nèi)部往往都使用了緩沖葫掉,會(huì)造成內(nèi)存泄漏,一定要確保關(guān)閉它并將引用置為null
  • WebView導(dǎo)致的內(nèi)存泄漏
    WebView只要使用一次跟狱,內(nèi)存就不會(huì)被釋放俭厚,所以WebView都存在內(nèi)存泄漏的問題,通常的解決辦法是為WebView單開一個(gè)進(jìn)程驶臊,使用AIDL進(jìn)行通信挪挤,根據(jù)業(yè)務(wù)需求在合適的時(shí)機(jī)釋放掉
  • 集合中的對(duì)象未清理
    集合用于保存對(duì)象,如果集合越來越大关翎,不進(jìn)行合理的清理扛门,尤其是入股集合是靜態(tài)的
  • Bitmap導(dǎo)致內(nèi)存泄漏
    bitmap是比較占內(nèi)存的,所以一定要在不使用的時(shí)候及時(shí)進(jìn)行清理纵寝,避免靜態(tài)變量持有大的bitmap對(duì)象
  • 監(jiān)聽器未關(guān)閉
    很多需要register和unregister的系統(tǒng)服務(wù)要在合適的時(shí)候進(jìn)行unregister,手動(dòng)添加的listener也需要及時(shí)移除

減少OOM

Android系統(tǒng)為每一個(gè)應(yīng)用程序都設(shè)置了一個(gè)硬性的Dalvik Heap Size最大限制閾值论寨,這個(gè)閾值在不同的設(shè)備上會(huì)因?yàn)镽AM大小不同而各有差異。ActivityManager.getMemoryClass()可以用來查詢當(dāng)前應(yīng)用的Heap Size閾值爽茴。命令行也可以查看相關(guān)的內(nèi)存信息
減少OOM方面:
其實(shí)避免內(nèi)存泄露也是間接避免了OOM

  • 減少內(nèi)存分配量
  • ArrayMap/SparseArray而不是HashMap等傳統(tǒng)數(shù)據(jù)結(jié)構(gòu)葬凳,通常的HashMap的實(shí)現(xiàn)方式更加消耗內(nèi)存,因?yàn)樗枰粋€(gè)額外的實(shí)例對(duì)象來記錄Mapping操作室奏。另外火焰,SparseArray更加高效在于他們避免了對(duì)key與value的autobox自動(dòng)裝箱,并且避免了裝箱后的解箱胧沫。
  • 避免在Android里面使用Enum
  • Android內(nèi)置字符串/顏色/圖片/動(dòng)畫/樣式以及簡單布局的使用昌简,可以在程序中直接飲用系統(tǒng)資源,減少apk體積琳袄,但要注意版本差異

APP啟動(dòng)優(yōu)化

一般情況下我們會(huì)利用主題去防止出現(xiàn)白屏
需要盡可能減少Application的onCreate中所要做的事情江场,比如一些不重要的SDK延遲或者異步加載;
有幾個(gè)方向:
1窖逗、利用開啟APP時(shí)候提前展示的window址否,快速展示一個(gè)界面,給用戶視覺上快速的感覺:onCreate函數(shù)開頭將activity的theme設(shè)置為style中的主題,然后在oncreate函數(shù)運(yùn)行過程中又切換成activity標(biāo)簽下配置的背景佑附。
2樊诺、異步初始化三方組件
3、減少IO音同、網(wǎng)絡(luò)等密集請(qǐng)求

線程優(yōu)化

采用線程池词爬,一是減少線程重復(fù)創(chuàng)建或銷毀帶來的性能損耗;
二是控制最大并發(fā)線程數(shù)权均,防止大量線程搶CPU造成卡頓

apk瘦身

為什么要瘦身:大體積下載轉(zhuǎn)化率低顿膨,同時(shí)對(duì)服務(wù)器增加流量壓力,此外會(huì)影響手機(jī)廠商預(yù)置應(yīng)用
利用ProGuard壓縮代碼去除無用資源叽赊,通過移除不需要的代碼恋沃,重命名類,域與方法等等對(duì)代碼進(jìn)行壓縮必指,優(yōu)化與混淆囊咏。使用ProGuard可以使得你的代碼更加緊湊,這樣能夠減少mapping代碼所需要的內(nèi)存空間塔橡。
使用 XZ 或者 7-Zip 壓縮Library
第三方開源庫的瘦身梅割,僅保留自己需要的部分
so的優(yōu)化與配置,只保留一類so
動(dòng)態(tài)下發(fā)一些資源:字庫葛家、so户辞、換膚包等

布局優(yōu)化

盡量減少布局層級(jí),同層級(jí)時(shí)候使用功能較低的ViewGroup惦银,比如FrameLayout和LinearLayout咆课,但性能較低的layout拓展性差難以實(shí)現(xiàn)較復(fù)雜的布局,導(dǎo)致需要嵌套扯俱,這時(shí)候還是建議使用RelativeLayout畢竟嵌套也會(huì)降低性能书蚪。
實(shí)用策略:

  • inlcude標(biāo)簽 便于布局重用
  • merge標(biāo)簽 和include配合使用,在被include的布局根元素替換為merge標(biāo)簽迅栅,能夠減少布局層級(jí)
  • ViewStub實(shí)現(xiàn)需要時(shí)加載布局殊校,setVisibility或者inflate之后,被內(nèi)部引用布局替換掉读存,提高應(yīng)用啟動(dòng)性能为流。

繪制優(yōu)化

為了讓屏幕的刷新幀率達(dá)到60fps,我們需要確保在時(shí)間16ms(1000/60Hz)內(nèi)完成單次刷新的操作(包括measure让簿、layout以及draw)
onDraw方法中不要?jiǎng)?chuàng)造大量臨時(shí)對(duì)象敬察,因?yàn)樵摲椒〞?huì)被頻繁調(diào)用,大量GC傷不起尔当。此外也不要使用耗時(shí)操作你懂的啦
減少overDraw的產(chǎn)生莲祸,盡量讓一個(gè)像素只繪制一次,減少布局重疊。
除了布局精簡锐帜,還可以去掉每行RelativeLayout的背景色田盈;去掉每行TextView的背景色;必要的話去掉activity使用的Theme的背景色缴阎。

ListView優(yōu)化

ListView只是一個(gè)代表允瞧,很多復(fù)雜的View都可以參考如下建議
使用ViewHolder并減少在getView中的復(fù)雜操作
根據(jù)滑動(dòng)速度來變化view的操作,比如快速滑動(dòng)時(shí)候不開啟線程
采用硬件加速來優(yōu)化view的繪制

Bitmap優(yōu)化

  • 采用BitmapFactory來對(duì)圖片進(jìn)行采樣
    inSampleSize:縮放比例蛮拔,在把圖片載入內(nèi)存之前述暂,我們需要先計(jì)算出一個(gè)合適的縮放比例,避免不必要的大圖載入建炫。
    decode format:解碼格式贸典,選擇ARGB_8888/RBG_565/ARGB_4444/ALPHA_8,存在很大差異踱卵。
  • 使用更小的圖片
    盡量使用更小的圖片不僅僅可以減少內(nèi)存的使用,還可以避免出現(xiàn)大量的InflationException据过。假設(shè)有一張很大的圖片被XML文件直接引用惋砂,很有可能在初始化視圖的時(shí)候就會(huì)因?yàn)閮?nèi)存不足而發(fā)生InflationException,這個(gè)問題的根本原因其實(shí)是發(fā)生了OOM绳锅。
  • 實(shí)現(xiàn)對(duì)象的復(fù)用
    LRU緩存

ANR分析

避免ANR的核心西路是不要在主線程做耗時(shí)操作西饵,ANR在activity中的規(guī)定出現(xiàn)時(shí)限是5秒,在廣播中是10秒
出現(xiàn)原因有主線程無法響應(yīng)觸摸或者用戶輸入鳞芙,線程之間等待死鎖等等眷柔。

電量優(yōu)化

為了減少電量的消耗,在蜂窩移動(dòng)網(wǎng)絡(luò)下原朝,最好做到批量執(zhí)行網(wǎng)絡(luò)請(qǐng)求驯嘱,盡量避免頻繁的間隔網(wǎng)絡(luò)請(qǐng)求
合理的使用一些傳感器、謹(jǐn)慎的使用Wake Lock
檢測可以利用battery-historian

其他建議

減少對(duì)象
減少枚舉
常量使用static final修飾
使用Android特有的數(shù)據(jù)結(jié)構(gòu)喳坠,如SparseArray和pair他們具備更好的性能
適當(dāng)使用弱引用和軟引用
采用內(nèi)存緩存和磁盤緩存
盡量使用靜態(tài)內(nèi)部類

性能優(yōu)化工具

Android Device Monitor(DDMS) was deprecated in Android Studio 3.1 and removed from Android Studio 3.2,此外鞠评,SYSTrace TraceView都被AndroidProfile取代了,不過特定場景上述工具還可用

性能分析工具分兩個(gè)流派:
第一個(gè)流派是 instrument壕鹉。獲取一段時(shí)間內(nèi)所有函數(shù)的調(diào)用過程剃幌,可以通過分析這段時(shí)間內(nèi)的函數(shù)調(diào)用流程,再進(jìn)一步分析待優(yōu)化的點(diǎn)晾浴。

第二個(gè)流派是 sample负乡。有選擇性或者采用抽樣的方式觀察某些函數(shù)調(diào)用過程,可以通過這些有限的信息推測出流程中的可疑點(diǎn)脊凰,然后再繼續(xù)細(xì)化分析抖棘。

  • TraceView屬于instrument類型,試圖收集某個(gè)階段所有函數(shù)的運(yùn)行信息,它希望在你并不知道哪個(gè)函數(shù)有問題的時(shí)候直接定位到關(guān)鍵函數(shù)钉答;但可惜的是础芍,收集所有信息 這個(gè)是不現(xiàn)實(shí)的,它的運(yùn)行時(shí)開銷嚴(yán)重干擾了運(yùn)行環(huán)境.

  • SYSTrace屬于sample類型数尿,它的思想很樸素仑性,在系統(tǒng)的一些關(guān)鍵鏈路(比如System Service,虛擬機(jī)右蹦,Binder驅(qū)動(dòng))插入一些信息(我這里稱之為Label)诊杆,通過Label的開始和結(jié)束來確定某個(gè)核心過程的執(zhí)行時(shí)間,然后把這些Label信息收集起來得到系統(tǒng)關(guān)鍵路徑的運(yùn)行時(shí)間信息何陆,進(jìn)而得到整個(gè)系統(tǒng)的運(yùn)行性能信息晨汹。Android Framework里面一些重要的模塊都插入了Label信息(Java層的通過android.os.Trace類完成,native層通過ATrace宏完成)贷盲,用戶App中可以添加自定義的Label淘这,這樣就組成了一個(gè)完成的性能分析系統(tǒng)。

在 Android Studio 3.2 的 Profiler 中直接集成了幾種性能分析工具巩剖,其中:Sample Java Methods 的功能類似于 Traceview 的 sample 類型铝穷。Trace Java Methods 的功能類似于 Traceview 的 instrument 類型。Trace System Calls 的功能類似于 systrace佳魔。SampleNative (API Level 26+) 的功能類似于 Simpleperf曙聂。坦白來說,Profiler 界面在某些方面不如這些工具自帶的界面鞠鲜,支持配置的參數(shù)也不如命令行宁脊,不過 Profiler 的確大大降低了開發(fā)者的使用門檻。

  • CPU profiler 存在于Android profile中贤姆,用于分析CUP動(dòng)態(tài)使用率榆苞,還可以分析函數(shù)調(diào)用關(guān)系,顯示線程任務(wù)的CPU使用率霞捡,它是TraceView和SYSTrace的替代工具

  • Tracer for OpenGL ES语稠,它可以記錄和分析app每一幀的繪制過程,以及列出所有用到OpenGL ES的繪制函數(shù)和耗時(shí)弄砍,所以通過Tracer for OpenGL ES我們可以很容易的看出app的每一幀是怎么畫出來的仙畦。已經(jīng)被Graphics API Debugger取代

  • LayoutInspector 查看運(yùn)行時(shí)的view結(jié)構(gòu)層級(jí),用來取代Hierarchy Viewer音婶,同樣取代了Pixel Perfect

  • Network Traffic tool If you need to view how and when your app transfers data over a network, use the Network Profiler

https://developer.android.google.cn/studio/profile/monitor.html

此外慨畸,優(yōu)化過程中使用低端手機(jī)更易發(fā)現(xiàn)瓶頸

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市衣式,隨后出現(xiàn)的幾起案子寸士,更是在濱河造成了極大的恐慌檐什,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,386評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件弱卡,死亡現(xiàn)場離奇詭異乃正,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)婶博,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,142評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門瓮具,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人凡人,你說我怎么就攤上這事名党。” “怎么了挠轴?”我有些...
    開封第一講書人閱讀 164,704評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵传睹,是天一觀的道長。 經(jīng)常有香客問我岸晦,道長欧啤,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,702評(píng)論 1 294
  • 正文 為了忘掉前任启上,我火速辦了婚禮堂油,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘碧绞。我一直安慰自己,他們只是感情好吱窝,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,716評(píng)論 6 392
  • 文/花漫 我一把揭開白布讥邻。 她就那樣靜靜地躺著,像睡著了一般院峡。 火紅的嫁衣襯著肌膚如雪兴使。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,573評(píng)論 1 305
  • 那天照激,我揣著相機(jī)與錄音发魄,去河邊找鬼。 笑死俩垃,一個(gè)胖子當(dāng)著我的面吹牛励幼,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播口柳,決...
    沈念sama閱讀 40,314評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼苹粟,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了跃闹?” 一聲冷哼從身側(cè)響起嵌削,我...
    開封第一講書人閱讀 39,230評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤毛好,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后苛秕,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體肌访,經(jīng)...
    沈念sama閱讀 45,680評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,873評(píng)論 3 336
  • 正文 我和宋清朗相戀三年艇劫,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了吼驶。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,991評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡港准,死狀恐怖旨剥,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情浅缸,我是刑警寧澤轨帜,帶...
    沈念sama閱讀 35,706評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站衩椒,受9級(jí)特大地震影響蚌父,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜毛萌,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,329評(píng)論 3 330
  • 文/蒙蒙 一苟弛、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧阁将,春花似錦膏秫、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,910評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至吹榴,卻和暖如春亭敢,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背图筹。 一陣腳步聲響...
    開封第一講書人閱讀 33,038評(píng)論 1 270
  • 我被黑心中介騙來泰國打工帅刀, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人远剩。 一個(gè)月前我還...
    沈念sama閱讀 48,158評(píng)論 3 370
  • 正文 我出身青樓扣溺,卻偏偏與公主長得像,于是被迫代替她去往敵國和親瓜晤。 傳聞我的和親對(duì)象是個(gè)殘疾皇子儒陨,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,941評(píng)論 2 355

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

  • Android作為一種移動(dòng)設(shè)備送漠,無論是內(nèi)存還是CPU性能都會(huì)有一定的限制原押,無法和PC設(shè)備相比擬,有鑒于此只估,Andr...
    乆丩乣閱讀 821評(píng)論 1 21
  • 周星馳的電影《功夫》里面借火云邪神之口說出了一句至理名言:“天下武功,唯快不破”着绷。 在移動(dòng)互聯(lián)網(wǎng)時(shí)代蛔钙,同樣如此,如...
    lipy_閱讀 949評(píng)論 0 2
  • 導(dǎo)語 Google官方的Android性能優(yōu)化典范專題短視頻課程是學(xué)習(xí)Android性能優(yōu)化極佳的課程荠医,目前已更新...
    一個(gè)有故事的程序員閱讀 827評(píng)論 0 1
  • ??使用過Android系統(tǒng)手機(jī)的同學(xué)都知道吁脱,Android手機(jī)越用越卡,這個(gè)卡主要體現(xiàn)在手機(jī)系統(tǒng)越用越卡彬向,打開A...
    alexlee1987閱讀 1,053評(píng)論 1 14
  • 書名:《小狗錢錢》 金句:第一章錢錢語錄 金錢有一些秘密和規(guī)律兼贡,想要了解這些秘密和規(guī)律,前提條件是娃胆,你自己必須真的...
    劉歡Fancy_Liuhuan閱讀 269評(píng)論 1 0