安卓性能優(yōu)化

  • 布局
  • 繪制
  • 啟動(dòng)
  • 內(nèi)存
  • apk

布局優(yōu)化

布局優(yōu)化的思路就是盡量避免布局文件的層級(jí)铐姚,避免OverDraw;
Overdraw:

就是過(guò)度繪制俭驮,是指在一幀的時(shí)間內(nèi)(16.67ms)像素被繪制了多次,理論上一個(gè)像素每次只繪制一次是最優(yōu)的,但是由于重疊的布局導(dǎo)致一些像素會(huì)被多次繪制,而每次繪制都會(huì)對(duì)應(yīng)到CPU的一組繪圖命令和GPU的一些操作,當(dāng)這個(gè)操作耗時(shí)超過(guò)16.67ms時(shí)娄帖,就會(huì)出現(xiàn)掉幀現(xiàn)象,也就是我們所說(shuō)的卡頓昙楚,所以對(duì)重疊不可見(jiàn)元素的重復(fù)繪制會(huì)產(chǎn)生額外的開(kāi)銷近速,需要盡量減少Overdraw的發(fā)生

檢測(cè)OverDraw:

  • 在開(kāi)發(fā)者選項(xiàng)中,打開(kāi)調(diào)試GPU過(guò)度繪制(Show GPU OverDraw)堪旧,會(huì)出現(xiàn)這個(gè)界面:
顏色 意義
沒(méi)有顏色 意味著沒(méi)有OverDraw削葱,像素只繪制了一次
藍(lán)色 意味著overdraw 1倍。像素繪制了兩次淳梦。大片的藍(lán)色還是可以接受的(若整個(gè)窗口是藍(lán)色的佩耳,可以擺脫一層)
綠色 意味著overdraw 2倍。像素繪制了三次谭跨。中等大小的綠色區(qū)域是可以接受的但你應(yīng)該嘗試優(yōu)化干厚、減少它們李滴。
淺紅 意味著overdraw 3倍。像素繪制了四次蛮瞄,小范圍可以接受所坯。
暗紅 意味著overdraw 4倍。像素繪制了五次或者更多挂捅。這是錯(cuò)誤的芹助,要修復(fù)它們。

如何優(yōu)化:

1. 合理布局xml:
  • 在編寫xml界面時(shí)闲先,刪除無(wú)用的控件和層次状土;
  • 其次如果一個(gè)界面LinearLayout和RelativeLayout都可以實(shí)現(xiàn),采用LinearLayout伺糠,因?yàn)镽elativeLayout的內(nèi)部實(shí)現(xiàn)較復(fù)雜蒙谓,布局過(guò)程會(huì)花費(fèi)更多的CPU事件;
2. 使用include训桶,merge累驮,ViewStub
  • 使用include標(biāo)簽復(fù)用布局文件
  • 使用merge標(biāo)簽配合include減少布局的層級(jí),如果被復(fù)用的布局文件有一層布局是不需要的,可以使用merge去掉多余的一層
  • ViewStub繼承View,它本身不參與任何的布局和繪制過(guò)程堡牡,作用于按需加載所需的布局文件;調(diào)用setVisibility()和inflate()后ViewStub才會(huì)生效置侍;
3. 使用ClipRect & QuickReject

為了解決Overdraw的問(wèn)題,Android系統(tǒng)會(huì)通過(guò)避免繪制那些完全不可見(jiàn)的組件來(lái)盡量減少消耗拦焚。但是不幸的是蜡坊,對(duì)于那些過(guò)于復(fù)雜的自定義的View(通常重寫了onDraw方法),Android系統(tǒng)無(wú)法檢測(cè)在onDraw里面具體會(huì)執(zhí)行什么操作耕漱,系統(tǒng)無(wú)法監(jiān)控并自動(dòng)優(yōu)化算色,也就無(wú)法避免Overdraw了抬伺。但是我們可以通過(guò)canvas.clipRect()來(lái)幫助系統(tǒng)識(shí)別那些可見(jiàn)的區(qū)域螟够。這個(gè)方法可以指定一塊矩形區(qū)域,只有在這個(gè)區(qū)域內(nèi)才會(huì)被繪制峡钓,其他的區(qū)域會(huì)被忽視妓笙。這個(gè)API可以很好的幫助那些有多組重疊組件的自定義View來(lái)控制顯示的區(qū)域。同時(shí)clipRect方法還可以幫助節(jié)約CPU與GPU資源能岩,在clipRect區(qū)域之外的繪制指令都不會(huì)被執(zhí)行寞宫,那些部分內(nèi)容在矩形區(qū)域內(nèi)的組件,仍然會(huì)得到繪制拉鹃。除了clipRect方法之外辈赋,我們還可以使用canvas.quickreject()來(lái)判斷是否沒(méi)和某個(gè)矩形相交鲫忍,從而跳過(guò)那些非矩形區(qū)域內(nèi)的繪制操作

Android畫布剪裁函數(shù)clipRect詳解
使用clipRect()優(yōu)化OverDraw
其實(shí)clipRect函數(shù)就是通過(guò)巧妙的剪裁和拼接畫布,將自定義控件中重疊的部分钥屈,做優(yōu)化處理悟民。

繪制優(yōu)化

繪制優(yōu)化指View的onDraw()過(guò)程要避免大量操作,主要體現(xiàn)在兩個(gè)方面:

  • 不能創(chuàng)建新的局部對(duì)象
  • 不能做耗時(shí)操作

因?yàn)閛nDraw過(guò)程是會(huì)被頻繁調(diào)用的篷就,大量的局部變量會(huì)占用過(guò)多的內(nèi)存射亏,并且會(huì)引發(fā)頻繁的GC,GC會(huì)影響程序的執(zhí)行效率(Stop the World);過(guò)多的耗時(shí)操作會(huì)十分消耗CPU的時(shí)間片竭业,導(dǎo)致View繪制的不流暢智润;官方規(guī)定View的繪制率保證在60fps最好,要求每幀的時(shí)間不超過(guò)16ms(1000/60)未辆,盡量降低onDraw方法的復(fù)雜度會(huì)有效的提高程序的效率窟绷;

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

啟動(dòng)的分類
  • 冷啟動(dòng):當(dāng)啟動(dòng)應(yīng)用時(shí),后臺(tái)沒(méi)有該應(yīng)用的進(jìn)程鼎姐,這時(shí)系統(tǒng)會(huì)首先會(huì)創(chuàng)建一個(gè)新的進(jìn)程分配給該應(yīng)用钾麸,這種啟動(dòng)方式就是冷啟動(dòng)
  • 熱啟動(dòng):當(dāng)啟動(dòng)應(yīng)用時(shí),后臺(tái)已有該應(yīng)用的進(jìn)程炕桨,比如按下home鍵饭尝,這種在已有進(jìn)程的情況下,這種啟動(dòng)會(huì)從已有的進(jìn)程中來(lái)啟動(dòng)應(yīng)用献宫,這種啟動(dòng)方式叫熱啟動(dòng)
  • 溫啟動(dòng):當(dāng)啟動(dòng)應(yīng)用時(shí)钥平,后臺(tái)已有該應(yīng)用的進(jìn)程,但是啟動(dòng)的入口Activity被干掉了姊途,比如按了back鍵涉瘾,應(yīng)用雖然退出了,但是該應(yīng)用的進(jìn)程是依然會(huì)保留在后臺(tái)捷兰,這種啟動(dòng)方式叫溫啟動(dòng)
啟動(dòng)時(shí)間的檢測(cè):
1.ADB命令: adb shell am start -W packagename/MainActivity
參數(shù) 含義
ThisTime 最后一個(gè)啟動(dòng)的Activity的啟動(dòng)耗時(shí)立叛;
TotalTime 新應(yīng)用啟動(dòng)的耗時(shí),包括新進(jìn)程的啟動(dòng)和Activity的啟動(dòng)
WaitTime ActivityManagerService啟動(dòng)App的Activity時(shí)的總時(shí)間(包括當(dāng)前Activity的onPause()和自己Activity的啟動(dòng))
冷啟動(dòng)白屏出現(xiàn)的原因:

ActivityStack的startActivityLock()會(huì)調(diào)用showStartingWindow() 添加一個(gè)空白的window贡茅;

處理冷啟動(dòng)白屏的方法:
  • 通過(guò)Theme設(shè)置window不顯示或者window設(shè)置為透明的


  • 為Theme設(shè)置背景圖

推薦第二種秘蛇,第一種如果根activity啟動(dòng)耗時(shí)的話會(huì)出現(xiàn)卡頓現(xiàn)象;

啟動(dòng)時(shí)的其他優(yōu)化

  • 多進(jìn)程Application重復(fù)創(chuàng)建顶考,動(dòng)態(tài)判斷包名避免重復(fù)初始化
  • 大量子線程任務(wù),設(shè)置工作線程的優(yōu)先級(jí)
  • 線程池的開(kāi)銷比單一線程大很多赁还,在啟動(dòng)的時(shí)候使用線程更優(yōu)
  • 信息未緩存,重復(fù)獲取影響性能

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

  • 內(nèi)存抖動(dòng):短時(shí)間內(nèi)大量的對(duì)象創(chuàng)建和銷毀會(huì)出現(xiàn)內(nèi)存抖動(dòng)
  • 內(nèi)存泄漏:對(duì)象內(nèi)存由于某些原因無(wú)法釋放和回收
  • 內(nèi)存溢出:大量的內(nèi)存泄漏會(huì)導(dǎo)致內(nèi)存溢出OOM
  • 內(nèi)存卡頓:安卓的垃圾收集器是CMS驹沿,CMS的Stop the World會(huì)造成卡頓
常見(jiàn)的字符串拼接會(huì)造成內(nèi)存的抖動(dòng):


addStr的字節(jié)碼

因?yàn)樽址莊inal常量艘策,一經(jīng)賦值就無(wú)法改變,但是java語(yǔ)言對(duì)+進(jìn)行了語(yǔ)法糖設(shè)置渊季,實(shí)際是將String轉(zhuǎn)化為StringBuffer朋蔫,每次都要new 一個(gè)StringBuffer出來(lái)罚渐;所以我們?nèi)绻苯邮褂肧tringBuffer的append()就可以避免重復(fù)創(chuàng)建StringBuffer對(duì)象;

預(yù)防內(nèi)存抖動(dòng):

  • 避免在循環(huán)中創(chuàng)建對(duì)象
  • 避免在重復(fù)調(diào)用的方法中創(chuàng)建局部對(duì)象
  • 使用對(duì)象池:Handler的Message的obtain()

內(nèi)存的檢測(cè)

  • AS自帶的Profiler


內(nèi)存泄漏的原因:長(zhǎng)生命周期對(duì)象持有短生命周期對(duì)象引用驯妄,導(dǎo)致短生命周期對(duì)象無(wú)法回收

常見(jiàn)的內(nèi)存泄漏:

  • 單例持有activity的引用
  • 外部類持有內(nèi)部類的引用(Hnadler搅轿,Runnable,Listener) 非靜態(tài)內(nèi)部類和匿名內(nèi)部類會(huì)默認(rèn)持有外部類的引用
  • 大量的強(qiáng)引用

內(nèi)存泄漏的檢測(cè):

  • leakCanary

避免內(nèi)存溢出OOM的措施:

  • 使用靜態(tài)內(nèi)部類
  • 使用WeakReference
  • 增加JVM啟動(dòng)參數(shù)的內(nèi)存大小
  • 注意資源的手動(dòng)回收(關(guān)閉流富玷,停止動(dòng)畫璧坟,注銷EventBus,刪除元素置null)

Bitmap優(yōu)化

APK瘦身

APK的結(jié)構(gòu):

目錄:
  • assets:存放應(yīng)用的資源赎懦,這些資源能夠通過(guò)AssetManager對(duì)象獲得
  • lib:包含了針對(duì)處理器層面的被編譯的代碼雀鹃。這個(gè)目錄針對(duì)每個(gè)平臺(tái)類型都有一個(gè)子目錄,比如armeabi, armeabi-v7a, arm64-v8a, x86, x86_64和mips励两。
  • res:包含了沒(méi)被編譯到resources.arsc的資源黎茎。
  • META-INF:包含CERT.SF和CERT.RSA簽名文件,也包含了MANIFEST.MF文件当悔。(譯注:校驗(yàn)這個(gè)APK是否被人改動(dòng)過(guò))
文件:
  • classes.dex:包含了能被Dalvik/Art虛擬機(jī)理解的 dex 文件格式的類傅瞻。
  • resources.arsc:包含了被編譯的資源。該文件包含了res/values目錄的所有配置的 xml 內(nèi)容盲憎。打包工具將 xml 內(nèi)容編譯成二進(jìn)制形式并壓縮嗅骄。這些內(nèi)容包含了語(yǔ)言字符串和styles,還包含了那些內(nèi)容雖然不直接存儲(chǔ)在resources.arsc文件中饼疙,但是給定了該內(nèi)容的路徑溺森,比如布局文件和圖片。所以又叫 資源映射表
  • AndroidManifest.xml:包含了主要的Android配置文件窑眯。這個(gè)文件列出了應(yīng)用名稱屏积、版本、訪問(wèn)權(quán)限磅甩、引用的庫(kù)文件炊林。該文件使用二進(jìn)制 xml 格式存儲(chǔ)。(譯注:該文件還能看到應(yīng)用的minSdkVersion, targetSdkVersion等信息)

瘦身步驟:

1. 使用Lint檢測(cè)res目錄卷要,刪除無(wú)用資源

Lint的使用

2. 壓縮圖片渣聚,或者使用svg,Webp,tinyPNG
3. 修改lib配置:

安卓系統(tǒng)現(xiàn)在支持7中CPU架構(gòu),每種架構(gòu)都支持一種ABI(二進(jìn)制接口却妨,Android binary interface)饵逐,每種ABI都定義了二進(jìn)制文件(.so文件)括眠,我們可以刪除其他的CPU架構(gòu)的適配彪标,只保留armeabi-v7a一種主流架構(gòu);

ndk     {
            //設(shè)置支持的so庫(kù)架構(gòu)
            abiFilters "armeabi-v7a"
        }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末掷豺,一起剝皮案震驚了整個(gè)濱河市捞烟,隨后出現(xiàn)的幾起案子薄声,更是在濱河造成了極大的恐慌,老刑警劉巖题画,帶你破解...
    沈念sama閱讀 218,941評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件默辨,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡苍息,警方通過(guò)查閱死者的電腦和手機(jī)缩幸,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)竞思,“玉大人表谊,你說(shuō)我怎么就攤上這事「桥纾” “怎么了爆办?”我有些...
    開(kāi)封第一講書人閱讀 165,345評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)课梳。 經(jīng)常有香客問(wèn)我距辆,道長(zhǎng),這世上最難降的妖魔是什么暮刃? 我笑而不...
    開(kāi)封第一講書人閱讀 58,851評(píng)論 1 295
  • 正文 為了忘掉前任跨算,我火速辦了婚禮,結(jié)果婚禮上椭懊,老公的妹妹穿的比我還像新娘漂彤。我一直安慰自己,他們只是感情好灾搏,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,868評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布挫望。 她就那樣靜靜地躺著,像睡著了一般狂窑。 火紅的嫁衣襯著肌膚如雪媳板。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 51,688評(píng)論 1 305
  • 那天泉哈,我揣著相機(jī)與錄音蛉幸,去河邊找鬼。 笑死丛晦,一個(gè)胖子當(dāng)著我的面吹牛奕纫,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播烫沙,決...
    沈念sama閱讀 40,414評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼匹层,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了锌蓄?” 一聲冷哼從身側(cè)響起升筏,我...
    開(kāi)封第一講書人閱讀 39,319評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤撑柔,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后您访,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體铅忿,經(jīng)...
    沈念sama閱讀 45,775評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評(píng)論 3 336
  • 正文 我和宋清朗相戀三年灵汪,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了檀训。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,096評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡享言,死狀恐怖肢扯,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情担锤,我是刑警寧澤蔚晨,帶...
    沈念sama閱讀 35,789評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站肛循,受9級(jí)特大地震影響铭腕,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜多糠,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,437評(píng)論 3 331
  • 文/蒙蒙 一累舷、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧夹孔,春花似錦被盈、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,993評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至怜俐,卻和暖如春身堡,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背拍鲤。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,107評(píng)論 1 271
  • 我被黑心中介騙來(lái)泰國(guó)打工贴谎, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人季稳。 一個(gè)月前我還...
    沈念sama閱讀 48,308評(píng)論 3 372
  • 正文 我出身青樓擅这,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親景鼠。 傳聞我的和親對(duì)象是個(gè)殘疾皇子仲翎,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,037評(píng)論 2 355

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

  • 2015新年伊始,Google發(fā)布了關(guān)于Android性能優(yōu)化典范的專題,一共16個(gè)短視頻谭确,每個(gè)3-5分鐘,幫助開(kāi)...
    huldaZhang閱讀 478評(píng)論 0 2
  • 布局優(yōu)化 0, UI渲染機(jī)制 人眼所看到的流暢畫面票渠,需要的幀數(shù)在40幀每秒到60幀每秒之間逐哈,最佳的ftp在60左右...
    hloong閱讀 1,398評(píng)論 0 18
  • 2015年伊始,Google發(fā)布了關(guān)于Android性能優(yōu)化典范的專題问顷, 一共16個(gè)短視頻昂秃,每個(gè)3-5分鐘,幫助開(kāi)...
    zizi192閱讀 541評(píng)論 0 3
  • 引言 1. Android性能優(yōu)化篇之內(nèi)存優(yōu)化--內(nèi)存泄漏 2.Android性能優(yōu)化篇之內(nèi)存優(yōu)化--內(nèi)存優(yōu)化分析...
    愛(ài)聽(tīng)音樂(lè)的小石頭閱讀 5,220評(píng)論 0 11
  • 作者/李可馨 興化板橋中學(xué)八年級(jí) 其實(shí)面對(duì)什么事杜窄,都要認(rèn)真對(duì)待肠骆,即便這是件很小的事。現(xiàn)在對(duì)小事認(rèn)真負(fù)責(zé) 以后就...
    唐金秀閱讀 555評(píng)論 6 15