前言
安卓開發(fā)大軍浩浩蕩蕩,經過近十年的發(fā)展始腾,Android技術優(yōu)化日異月新州刽,Android系統(tǒng)性能也已經非常流暢,可以在體驗上完全媲美iOS浪箭。
但是穗椅,到了各大廠商手里,改源碼奶栖、自定義系統(tǒng)匹表,使得Android原生系統(tǒng)變得魚龍混雜,然后到了不同層次的開發(fā)工程師手里宣鄙,因為技術水平的參差不齊袍镀,即使很多手機在跑分軟件性能非常高,打開應用依然存在卡頓現象框冀。另外,隨著產品內容迭代敏簿,功能越來越復雜明也,UI頁面也越來越豐富,也成為流暢運行的一種阻礙惯裕。綜上所述温数,對APP進行性能優(yōu)化已成為開發(fā)者該有的一種綜合素質,也是開發(fā)者能夠完成高質量應用程序作品的保證蜻势。
在Android應用優(yōu)化方面撑刺,我們主要從以下4個方面進行優(yōu)化:
- 穩(wěn)定(內存溢出、崩潰)
- 流暢(卡頓)
- 耗損(耗電握玛、流量够傍、網絡)
- 安裝包(APK瘦身)
內存優(yōu)化
由于Android應用的沙箱機制,每個應用所分配的內存大小是有限度的挠铲,內存太低就會觸發(fā)LMK(Low Memory Killer)機制冕屯,進而會出現閃退現象。如果要對內存進行優(yōu)化拂苹,就需要先搞懂java的內存是如何分配和回收的安聘。
分析工具
Memory Monitor 工具
Memory Monitor是Android Studio自帶的一個內存監(jiān)視工具,它可以很好地幫助我們進行內存實時分析。通過點擊Android Studio右下角的Memory Monitor標簽浴韭,打開工具可以看見較淺藍色代表free的內存丘喻,而深色的部分代表使用的內存從內存變換的走勢圖變換,可以判斷關于內存的使用狀態(tài)念颈,例如當內存持續(xù)增高時泉粉,可能發(fā)生內存泄漏;當內存突然減少時舍肠,可能發(fā)生GC等搀继。
Memory Analyzer工具
MAT 是一個快速狞换,功能豐富的 Java Heap 分析工具宋欺,通過分析 Java 進程的內存快照 HPROF 分析嘁灯,從眾多的對象中分析汇陆,快速計算出在內存中對象占用的大小欺嗤,查看哪些對象不能被垃圾收集器回收枫浙,并可以通過視圖直觀地查看可能造成這種結果的對象匾委。
LeakCanary工具
LeakCanary是一個內存監(jiān)測工具让虐,該工具是Square公司出品的谍夭,所謂Square出品必屬精品黑滴,LeakCanary的官方地址為https://github.com/square/lea...,我們可以在Gradle里引用它紧索。
Android Lint 工具
Android Lint 是Android Sutido種集成的一個Android代碼提示工具袁辈,它可以給布局、代碼提供非常強大的幫助珠漂。如果在布局文件中寫了三層冗余的LinearLayout布局晚缩,就會在編輯器右邊看到提示。當然這個是一個簡單的舉例媳危,Lint的功能非常強大荞彼,大家應該養(yǎng)成寫完代碼查看Lint的習慣,這不僅讓你及時發(fā)現代碼種隱藏的一些問題待笑,更能讓你養(yǎng)成良好的代碼風格鸣皂,要知道,這些Lint提示可都是Google大牛們汗水合智慧的結晶暮蹂。
其他建議
在Android應用開發(fā)中寞缝,影響穩(wěn)定性的原因很多,比如內存使用不合理仰泻、代碼異常場景考慮不周全第租、代碼邏輯不合理等,都會對應用的穩(wěn)定性造成影響我纪。
其中最常見的兩個場景是:Crash 和 ANR慎宾,這兩個錯誤將會使得程序無法使用丐吓。所以做好Crash監(jiān)控,把崩潰信息趟据、異常信息收集記錄起來券犁,以便后續(xù)分析;合理使用主線程處理業(yè)務汹碱,不要在主線程中做耗時操作粘衬,防止ANR程序無響應發(fā)生。
交互優(yōu)化
交互是與用戶體驗最直接的方面咳促,交互場景大概可以分為四個部分:UI 繪制稚新、應用啟動、頁面跳轉跪腹、事件響應褂删。對于上面四個方面,大致可以從以下兩個方面來進行優(yōu)化:
- 界面繪制:主要原因是繪制的層級深冲茸、頁面復雜屯阀、刷新不合理,由于這些原因導致卡頓的場景更多出現在 UI 和啟動后的初始界面以及跳轉到頁面的繪制上轴术。
- 數據處理:導致這種卡頓場景的原因是數據處理量太大难衰,一般分為三種情況,一是數據在處理 UI 線程逗栽,二是數據處理占用 CPU 高盖袭,導致主線程拿不到時間片,三是內存增加導致 GC 頻繁彼宠,從而引起卡頓鳄虱。
我們知道,Android的繪制需要經過onMeasure兵志、onLayout醇蝴、onDraw等幾個步驟宣肚,所以布局的層級越深想罕、元素越多、耗時也就越長霉涨。還有就是Android 系統(tǒng)每隔 16ms 發(fā)出 VSYNC 信號按价,觸發(fā)對 UI 進行渲染,如果每次渲染都成功笙瑟,這樣就能夠達到流暢的畫面所需的 60FPS楼镐。如果某個操作花費的時間是 24ms ,系統(tǒng)在得到 VSYNC 信號時就無法正常進行正常渲染往枷,這樣就發(fā)生了丟幀現象框产。
之所以出現卡頓現象凄杯,是因為有兩個原因:
- 繪制任務太重,繪制一幀內容耗時太長
- 主線程太忙秉宿,根據系統(tǒng)傳遞過來的 VSYNC 信號來時還沒準備好數據導致丟幀
基于問題產生的原因戒突,我們可以從以下幾個方面進行優(yōu)化:
布局優(yōu)化
在Android種系統(tǒng)對View進行測量、布局和繪制時描睦,都是通過對View數的遍歷來進行操作的膊存。如果一個View數的高度太高就會嚴重影響測量、布局和繪制的速度忱叭。Google也在其API文檔中建議View高度不宜哦過10層「羝椋現在版本種Google使用RelativeLayout替代LineraLayout作為默認根布局,目的就是降低LineraLayout嵌套產生布局樹的高度韵丑,從而提高UI渲染的效率爵卒。
在布局優(yōu)化方面,我們可以從以下幾個方面進行優(yōu)化:
- 布局復用埂息,使用
<include>
標簽重用layout技潘; - 提高顯示速度,使用
<ViewStub>
延遲View加載千康; - 減少層級享幽,使用
<merge>
標簽替換父級布局; - 注意使用wrap_content拾弃,會增加measure計算成本值桩;
- 刪除控件中無用屬性;
渲染優(yōu)化
過度繪制是指在屏幕上的某個像素在同一幀的時間內被繪制了多次豪椿。在多層次重疊的 UI 結構中奔坟,如果不可見的 UI 也在做繪制的操作,就會導致某些像素區(qū)域被繪制了多次搭盾,從而浪費了多余的 CPU 以及 GPU 資源咳秉。我們可以通過開啟手機的過渡繪制功能來檢測頁面是否被過度繪制。
為了避免過度繪制鸯隅,我們可以從以下幾個方面進行優(yōu)化:
- 布局上的優(yōu)化澜建,移除 XML 中非必須的背景,移除 Window 默認的背景蝌以、按需顯示占位背景圖片炕舵。
- 自定義View優(yōu)化,使用 canvas.clipRect()來幫助系統(tǒng)識別那些可見的區(qū)域跟畅,只有在這個區(qū)域內才會被繪制咽筋。
啟動優(yōu)化
應用一般都有閃屏頁,優(yōu)化閃屏頁的 UI 布局徊件,可以通過 Profile GPU Rendering 檢測丟幀情況奸攻。
也可以通過啟動加載邏輯優(yōu)化蒜危。可以采用分布加載睹耐、異步加載舰褪、延期加載策略來提高應用啟動速度。
數據準備疏橄。數據初始化分析占拍,加載數據可以考慮用線程初始化等策略。
刷新優(yōu)化
Android開發(fā)中捎迫,通常是異步操作頁面的晃酒,因此需要可以從刷新優(yōu)化上來優(yōu)化應用,主要有兩個原則:
- 減少刷新次數窄绒;
- 縮小刷新區(qū)域贝次;
動畫優(yōu)化
在實現動畫效果時,需要根據不同場景選擇合適的動畫框架來實現彰导。有些情況下蛔翅,可以用硬件加速方式來提供流暢度。
耗電優(yōu)化
在移動設備中位谋,電池的重要性不言而喻山析,沒有電什么都干不成。對于操作系統(tǒng)和設備開發(fā)商來說掏父,耗電優(yōu)化一致沒有停止笋轨,去追求更長的待機時間,而對于一款應用來說赊淑,并不是可以忽略電量使用問題爵政,特別是那些被歸為“電池殺手”的應用,最終的結果是被卸載陶缺。因此钾挟,應用開發(fā)者在實現需求的同時,需要盡量減少電量的消耗饱岸。
在 Android5.0 以前掺出,在應用中測試電量消耗比較麻煩,也不準確伶贰,5.0 之后專門引入了一個獲取設備上電量消耗信息的 API蛛砰,即Battery Historian罐栈。Battery Historian 是一款由 Google 提供的 Android 系統(tǒng)電量分析工具黍衙,和Systrace 一樣,是一款圖形化數據分析工具荠诬,直觀地展示出手機的電量消耗過程琅翻,通過輸入電量分析文件位仁,顯示消耗情況,最后提供一些可供參考電量優(yōu)化的方法方椎。
網絡優(yōu)化
對于網絡的優(yōu)化聂抢,可以從以下幾個方面著手進行:
圖片網絡優(yōu)化
例如,針對網絡情況棠众,返回不同的圖片數據琳疏,一種是高清大圖,一種是正常圖片闸拿,一種是縮略小圖空盼。當用戶處于wifi下給控件設置高清大圖,當4g或者3g模式下加載正常圖片揽趾,當弱網條件下加載縮略圖。
網絡數據優(yōu)化
移動端獲取網絡數據優(yōu)化可以從以下幾點著手:
- 連接復用:節(jié)省連接建立時間篱瞎,如開啟 keep-alive痒芝。
對于Android來說默認情況下HttpURLConnection和HttpClient都開啟了keep-alive俐筋。只是2.2之前HttpURLConnection存在影響連接池的Bug,具體可見:Android HttpURLConnection及HttpClient選擇
- 請求合并:即將多個請求合并為一個進行請求严衬,比較常見的就是網頁中的CSS Image Sprites。如果某個頁面內請求過多瞳步,也可以考慮做一定的請求合并。
- 減少請求數據的大械テ稹:對于post請求抱怔,body可以做gzip壓縮的,header也可以做數據壓縮嘀倒。返回數據的body也可以做gzip壓縮屈留,body數據體積可以縮小到原來的30%左右测蘑。
異常攔截優(yōu)化
在獲取數據的流程中,訪問接口和解析數據時都有可能會出錯勇蝙,我們可以通過攔截器在這兩層攔截錯誤挨约。
- 在訪問接口時产雹,我們不用設置攔截器,因為一旦出現錯誤蔓挖,Retrofit會自動拋出異常馆衔。比如,常見請求異常404荒适,500开镣,503等等刀诬。
- 在解析數據時陕壹,我們設置一個攔截器树埠,判斷Result里面的code是否為成功,如果不成功怎憋,則要根據與服務器約定好的錯誤碼來拋出對應的異常。比如绊袋,token失效,禁用同賬號登陸多臺設備皂岔,缺少參數展姐,參數傳遞異常等等。
APK瘦身
應用安裝包大小對應用使用沒有影響教馆,但應用的安裝包越大擂达,用戶下載的門檻越高,特別是在移動網絡情況下,用戶在下載應用時,對安裝包大小的要求更高穗熬,因此,減小安裝包大小可以讓更多用戶愿意下載和體驗產品探遵。
在Android Studio工具欄里妓柜,打開build–>Analyze APK, 選擇要分析的APK包 ,可以看到apk的相關信息藏雏,如下所示:
Android的apk主要有以下信息構成:
- assets文件夾作煌。存放一些配置文件、資源文件粟誓,assets不會自動生成對應的 ID,而是通過 AssetManager 類的接口獲取病瞳。
- res悲酷。res 是 resource 的縮寫,這個目錄存放資源文件设易,會自動生成對應的 ID 并映射到 .R 文件中亡嫌,訪問直接使用資源ID。
- META-INF挟冠。保存應用的簽名信息,簽名信息可以驗證 APK 文件的完整性肋僧。
- AndroidManifest.xml。這個文件用來描述 Android 應用的配置信息嫌吠,一些組件的注冊信息、可使用權限等凭戴。
- classes.dex炕矮。Dalvik 字節(jié)碼程序,讓 Dalvik 虛擬機可執(zhí)行肤视,一般情況下邢滑,Android 應用在打包時通過Android SDK 中的 dx 工具將 Java 字節(jié)碼轉換為 Dalvik 字節(jié)碼。
- resources.arsc困后。記錄著資源文件和資源 ID 之間的映射關系,用來根據資源 ID 尋找資源锯仪。
基于上面的組成部分趾盐,那么優(yōu)化也可以從以下幾個方面著手:
- 代碼混淆。使用proGuard 代碼混淆器工具救鲤,它包括壓縮本缠、優(yōu)化、混淆等功能丹锹。
- 資源優(yōu)化。比如使用 Android Lint 刪除冗余資源匾灶,資源文件最少化等租漂。
- 圖片優(yōu)化颊糜。比如利用 AAPT 工具對 PNG 格式的圖片做壓縮處理秃踩,降低圖片色彩位數等。
- 避免重復功能的庫鸟赫,使用 WebP圖片格式等芍秆。
- 插件化翠勉,比如功能模塊放在服務器上,按需下載对碌,可以減少安裝包大小朽们。
更多Android可以瞧瞧我的個人介紹!F锿选!