Android性能優(yōu)化總結

最近大半個月都在做app的優(yōu)化泛烙,最主要是從apk包大小理卑、界面過度繪制、掉幀胶惰、內(nèi)存抖動傻工、主線程IO這幾個方面來入手的。相比開發(fā)新功能孵滞,做優(yōu)化真的是更費腦力和心神中捆,因為也許你做了大量的修改和優(yōu)化操作,能看見的效果卻微乎其微坊饶,但又不得不做泄伪。我想對于大多數(shù)Android開發(fā)者來說,開發(fā)出一款app并不難匿级,但是開發(fā)出一款高性能體驗棒的app卻并不是每個開發(fā)者都能做到的蟋滴。在開發(fā)過程中染厅,可能會因為各種各樣的原因會使你開發(fā)出來的app性能不佳,體驗很差津函,開發(fā)者寫代碼的水平肯定是最重要的因素肖粮,另外還有一些第三方SDK也可以能會引起你的app出現(xiàn)問題。

今天抽空把這大半個月以來優(yōu)化的過程和心得記錄一下尔苦。

apk包大小

無論是個人開發(fā)者自己開發(fā)的產(chǎn)品還是公司開發(fā)的產(chǎn)品涩馆,盡可能減小apk包的大小可以大大提高app的下載轉化率,所以優(yōu)化過程中apk體積是開發(fā)者必須要注意的一點允坚。我們先看看apk包是由哪些部分組成的魂那。我們可以使用Android Studio自帶的功能Build->Analyze APK,下圖是微信的apk組成:

wechat_apk
  • lib 存放app所需的native庫文件
  • classes.dex 開發(fā)者編寫的java文件最后都會轉化成dex文件運行在Android虛擬機上
  • assets 存放需要保持原始文件的資源文件
  • res 存放所有的資源文件
  • resource.arsc 所有資源文件的id映射
  • META-INF 簽名校驗文件
  • AndroldManifest.xml Android應用全局配置文件
  • 其它一些配置文件和第三方庫生成的文件

刪除無用資源

首先我從資源文件入手稠项。我們可以使用Android Studio中的工具搜索項目中沒有使用的的資源文件:

run-inspection-by-name

然后通過unused resources這個功能來查找:

unused-resources

查找完成后會把整個項目中未被使用的資源列出來涯雅,但是這個清理的時候我們需要注意下,有些資源文件可能是在你的項目中有用到的展运,但是資源id未出現(xiàn)在項目中的活逆,比如你在代碼中是通過資源名來獲取這個資源而不是通過資源id,這種情況下的資源就不能刪了拗胜,否則就會出錯划乖。另外一些第三方庫的資源文件也要小心誤刪。

關于保留幾種屏幕分辨率的資源文件

隨著目前手機市場的發(fā)展挤土,屏幕越來越大琴庵,分辨率越來越高,但是基于成本的考慮仰美,仍然還有一些相對較低的分辨率的機型迷殿,而我們的app是適配所有分辨率的機型,還是針對一些主流的機型做適配咖杂,這取決于我們app所適用的人群范圍庆寺。我們UI設計師一般是設計xxhdpi(480dpi)和xhdpi(320dpi)兩套,基本上可以滿足絕大部分的手機屏幕了诉字,如果你的app對apk體積有極高的要求懦尝,那么你也可以只選擇一套分辨率的素材。

資源壓縮

圖片壓縮:一般UI給我們的圖片都可以壓縮壤圃,我一般采用tinypng在線壓縮陵霉,支持png/jpg格式,為了避免失真伍绳,不要對同一張圖片壓縮多次踊挠。如果是Mac系統(tǒng)下,還可以選擇ImageOptim冲杀。

使用SVG圖片:SVG圖片即矢量圖效床,簡單的說睹酌,就是縮放不失真的圖像格式。使用矢量圖的好處有很多剩檀,可被非常多的工具讀取和修改(比如記事本)憋沿。SVG與JPEG和GIF圖像比起來,尺寸更小沪猴,且可壓縮性更強卤妒。SVG是可伸縮的,SVG圖像可在任何的分辨率下被高質(zhì)量地打印字币,SVG可在圖像質(zhì)量不下降的情況下被放大,SVG圖像中的文本是可選的共缕,同時也是可搜索的(很適合制作地圖)洗出,SVG可以與Java技術一起運行,SVG文件是純粹的XML图谷。使用Android Studio也可以將下載的svg格式的矢量圖轉化為xml格式翩活。比如我一般在阿里的Iconfont上下載一些簡單的圖標蔓挖,它可以選擇svg格式下載缓艳,然后在Android Studio的drawable文件夾右鍵NEW->Vector Asset:

然后會進到下面這個界面:

其中Asset Type類型中Material Icon是通過系統(tǒng)自帶的一些符合Material Design設計的icon來制作,Local file就是通過我們自己下載的svg文件來制作禀梳,完成后svg格式的文件就轉化成xml格式保存在我們的目標文件夾里了承璃。當然普通的ImageView是無法使用矢量圖的利耍,必須使用v7包下的AppCompatImageView,而且不能使用src屬性盔粹,必須是app:srcCompat屬性才可以隘梨。

用jpg代替png:因為jpg沒有alpha通道,所以文件更小舷嗡,比較適合于不需要透明度的圖片轴猎。

用shape、color來代替圖片:如果是漸變背景或者純顏色的控件背景进萄,都可以使用shape或者color做背景捻脖,一個xml文件相比一張位圖要小得多。

使用混淆

混淆除了代碼壓縮代碼混淆的功能還有資源壓縮的作用中鼠,在app module的build.gradle文件中配置shrinkResources true和minifyEnabled true這兩個參數(shù)可婶,就可以達到混淆壓縮的目的。關于混淆援雇,參看這篇文章 Android代碼混淆與進階

native庫文件

native庫都是為了支持不同架構的CPU扰肌,雖然native庫文件是占整個apk體積最大的部分,減少對其中一些CPU架構的支持可以很直觀的看到變化熊杨。關于so文件的知識和它的適配曙旭,可以看看下面幾篇文章盗舰,會有很大幫助。

過度繪制

首先我們得知道桂躏,過度繪制這個概念钻趋,到底什么是過渡繪制?UI過度繪制簡單的來說是指在一個界面中有很多元素剂习,但是我們只需要更新某一小塊的元素蛮位,app卻把所有的元素都刷新一遍,這就造成過度繪制鳞绕。過度繪制會造成GPU資源浪費失仁,引起我們的app頁面卡頓,掉幀現(xiàn)象们何。

overdraw_options_view

上圖是UI界面的過度繪制的情況萄焦,不同的顏色代表被過度繪制的次數(shù),開發(fā)者可以在手機設置的開發(fā)者選項中將“調(diào)式過度繪制”選項開啟冤竹,然后就可以看到界面上顯示不同的顏色了拂封。我們優(yōu)化的目的就是盡可能讓界面上只看到藍色或綠色,盡量不要出現(xiàn)大量的紅色鹦蠕。

怎么做才能減少紅色部分冒签?盡量將我們的layout布局層次簡單化,移除Window默認的background钟病,移除layout中非必須的background等萧恕,UI布局層次不應該過多,否則系統(tǒng)繪制UI時會占用較多時間肠阱,引起掉幀廊鸥。

更詳細的優(yōu)化方法請看

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

內(nèi)存抖動是因為在短時間內(nèi)大量的對象被創(chuàng)建又馬上被釋放。瞬間產(chǎn)生大量的對象會嚴重占用Young Generation的內(nèi)存區(qū)域辖所,當達到閥值惰说,剩余空間不夠的時候,會觸發(fā)GC從而導致剛產(chǎn)生的對象又很快被回收缘回。即使每次分配的對象占用了很少的內(nèi)存吆视,但是他們疊加在一起會增加Heap的壓力,從而觸發(fā)更多其他類型的GC酥宴。這個操作有可能會影響到幀率啦吧,并使得用戶感知到性能問題。如果你在Memory Monitor里面查看到短時間發(fā)生了多次內(nèi)存的漲跌拙寡,這意味著很有可能發(fā)生了內(nèi)存抖動授滓。同時我們還可以通過Allocation Tracker來查看在短時間內(nèi),同一個棧中不斷進出的相同對象。這是內(nèi)存抖動的典型信號之一般堆。當你大致定位問題之后在孝,接下去的問題修復也就顯得相對直接簡單了。例如淮摔,你需要避免在for循環(huán)里面分配對象占用內(nèi)存私沮,需要嘗試把對象的創(chuàng)建移到循環(huán)體之外,自定義View中的onDraw方法也需要引起注意和橙,每次屏幕發(fā)生繪制以及動畫執(zhí)行過程中仔燕,onDraw方法都會被調(diào)用到,避免在onDraw方法里面執(zhí)行復雜的操作魔招,避免創(chuàng)建對象晰搀。對于那些無法避免需要創(chuàng)建對象的情況,我們可以考慮對象池模型办斑,通過對象池來解決頻繁創(chuàng)建與銷毀的問題外恕,但是這里需要注意結束使用之后,需要手動釋放對象池中的對象俄周。

啟動時間(冷啟動,暖啟動髓迎,熱啟動)

app的啟動分為三種狀態(tài)峦朗,冷啟動即應用從零開始加載運行,而其它狀態(tài)則是應用從后臺運行回到前臺運行排龄。

冷啟動狀態(tài):系統(tǒng)不存在該應用的進程波势,啟動應用才創(chuàng)建出應用的進程。冷啟動一般指的就是應用在開機后或者被系統(tǒng)停止后的第一次啟動過程橄维。因為系統(tǒng)和應用在冷啟動時需要做更多的工作尺铣,所以減少它的啟動時間的難度是最大的。

冷啟動初始時争舞,系統(tǒng)完成三個任務:

  • 啟動和加載應用(這里泛指的是應用本身)
  • 創(chuàng)建應用的專屬進程
  • 啟動后立刻顯示啟動視圖(通常是個空白屏)

一旦系統(tǒng)創(chuàng)建了應用的專屬進程凛忿,該進程開始創(chuàng)建應用:

  • 創(chuàng)建應用對象
  • 啟動主線程 (MainThread)
  • 創(chuàng)建 Launcher Activity
  • 加載視圖 (Inflating views)
  • 渲染布局 (Laying out)
  • 執(zhí)行初始繪制

當應用完成了第一次繪制,系統(tǒng)進程就把當前顯示的啟動視圖切換為應用界面竞川,用戶就可以使用應用了店溢。

應用進程的啟動流程可以分為:Application的創(chuàng)建和Launcher Activity的創(chuàng)建,Application的創(chuàng)建是從Application.onCreate()開始的委乌,重寫onCreate()方法通常我們會在這里完成一些通用組件和第三方SDK的初始化操作床牧。接著應用程序生成主線程,并開始創(chuàng)建Launcher Activity遭贸。創(chuàng)建Activity的過程分為初始化戈咳、調(diào)用構造方法、調(diào)用當前生命周期的回調(diào)方法。通常onCreate()方法對加載時間的影響最大著蛙,因為它要執(zhí)行加載删铃、渲染和初始化Activity所需要的對象等開銷最大的任務,如果Activity的布局過于復雜册踩,那么就很可能會導致啟動性能問題泳姐。

暖啟動狀態(tài):應用程序的暖啟動與冷啟動類似,但比冷啟動開銷低暂吉。在暖啟動中胖秒,系統(tǒng)只需要把 Activity 切換到前臺運行。如果應用的該 Activity 之前駐留在內(nèi)存中慕的,那么應用程序就不用重新初始化對象和渲染布局阎肝。但是,如果由于響應了低內(nèi)存事件肮街,例如在 onTrimMemory() 方法中清除了資源對象风题,那么這些對象就需要在熱啟動時重新創(chuàng)建。

熱啟動狀態(tài):熱啟動為冷啟動的過程操作的子集嫉父,而且開銷比暖啟動稍小沛硅。以下這些情況可以認為是熱啟動:

  • 用戶退出應用,但隨后重新啟動它绕辖。應用的進程還在運行摇肌,但應用必須重新從 onCreate() 開始創(chuàng)建 Activity。
  • 系統(tǒng)從內(nèi)存中清除了應用(非用戶主動)仪际,然后用戶重新啟動它围小。進程和 Activity 需要重新啟動,但 onCreate() 將接收到保存狀態(tài)的 Bundle树碱。事實上肯适,savedInstanceState 在用戶未主動銷毀 Activity 時系統(tǒng)就會調(diào)用。

啟動時間的優(yōu)化:

一般我們優(yōu)化啟動時間都是基于冷啟動時間的成榜,所以主要是創(chuàng)建應用和創(chuàng)建Activity這兩部分所花時間的優(yōu)化框舔,在Application.onCreate()方法中,要盡量避免創(chuàng)建太多臨時變量赎婚、執(zhí)行IO操作雨饺、以及反序列化操作、多重for循環(huán)等惑淳。而在創(chuàng)建Launcher Activity過程中额港,布局視圖要盡量層次簡單,讓繪制過程盡量短歧焦,加載大量資源時可以選擇懶加載方式移斩。

關于啟動視圖:

之前說過當應用啟動后而且Launcher Activity的布局還沒有被渲染完成時肚医,會出現(xiàn)一個空白屏,如果Launcher Activity的布局非常復雜向瓷,渲染消耗的時間很長肠套,那用戶可能會感知到這個空白屏的存在,體驗上來說猖任,是很不友好的你稚,那么怎么解決這個問題呢?我們可以使用windowBackground這個屬性朱躺,一般我們會設置成一張圖片刁赖,然后在AndroidManifest.xml中的application節(jié)點的Theme中加上這個屬性。這樣做之后长搀,當應用被點擊后立馬就可以看到這張圖片宇弛,而不是一個空白屏了。

主線程IO

如果在主線程中有讀寫文件等這些耗時的操作源请,就會阻塞主線程枪芒,影響app的性能。所以在主線程中谁尸,不要進行IO操作舅踪,也不要進行for循環(huán)創(chuàng)建大量的對象。如果必須要操作IO良蛮,也要放在子線程中或者Service中進行抽碌,以保證主線程不會被阻塞。

64K 引用限制

關于64k引用限制背镇,官方的說明文檔:配置方法數(shù)超過 64K 的應用咬展,規(guī)避64k限制的辦法就是采用Dalvik可執(zhí)行文件分包泽裳。具體的配置方法請看文檔說明瞒斩。

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市涮总,隨后出現(xiàn)的幾起案子胸囱,更是在濱河造成了極大的恐慌,老刑警劉巖瀑梗,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件烹笔,死亡現(xiàn)場離奇詭異,居然都是意外死亡抛丽,警方通過查閱死者的電腦和手機谤职,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來亿鲜,“玉大人允蜈,你說我怎么就攤上這事。” “怎么了饶套?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵漩蟆,是天一觀的道長。 經(jīng)常有香客問我妓蛮,道長怠李,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任蛤克,我火速辦了婚禮捺癞,結果婚禮上,老公的妹妹穿的比我還像新娘咖耘。我一直安慰自己翘簇,他們只是感情好,可當我...
    茶點故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布儿倒。 她就那樣靜靜地躺著版保,像睡著了一般。 火紅的嫁衣襯著肌膚如雪夫否。 梳的紋絲不亂的頭發(fā)上彻犁,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天,我揣著相機與錄音凰慈,去河邊找鬼汞幢。 笑死,一個胖子當著我的面吹牛微谓,可吹牛的內(nèi)容都是我干的森篷。 我是一名探鬼主播,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼豺型,長吁一口氣:“原來是場噩夢啊……” “哼仲智!你這毒婦竟也來了?” 一聲冷哼從身側響起姻氨,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤钓辆,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后肴焊,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體前联,經(jīng)...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年娶眷,在試婚紗的時候發(fā)現(xiàn)自己被綠了似嗤。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,090評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡届宠,死狀恐怖烁落,靈堂內(nèi)的尸體忽然破棺而出壳咕,到底是詐尸還是另有隱情,我是刑警寧澤顽馋,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布谓厘,位于F島的核電站,受9級特大地震影響寸谜,放射性物質(zhì)發(fā)生泄漏竟稳。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一熊痴、第九天 我趴在偏房一處隱蔽的房頂上張望他爸。 院中可真熱鬧,春花似錦果善、人聲如沸诊笤。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽讨跟。三九已至,卻和暖如春鄙煤,著一層夾襖步出監(jiān)牢的瞬間晾匠,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工梯刚, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留凉馆,地道東北人。 一個月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓亡资,卻偏偏與公主長得像澜共,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子锥腻,可洞房花燭夜當晚...
    茶點故事閱讀 45,033評論 2 355

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