Android性能優化總結

安卓開發大軍浩浩蕩蕩,經過近十年的發展,Android技術優化日異月新,如今Android 9.0 已經發布,Android系統性能也已經非常流暢,可以在體驗上完全媲美iOS。
但是,到了各大廠商手里,改源碼、自定義系統,使得Android原生系統變得魚龍混雜,然后到了不同層次的開發工程師手里,因為技術水平的參差不齊,即使很多手機在跑分軟件性能非常高,打開應用依然存在卡頓現象。另外,隨著產品內容迭代,功能越來越復雜,UI頁面也越來越豐富,也成為流暢運行的一種阻礙。綜上所述,對APP進行性能優化已成為開發者該有的一種綜合素質,也是開發者能夠完成高質量應用程序作品的保證。

在Android應用優化方面,我們主要從以下4個方面進行優化:

  1. 穩定(內存溢出、崩潰)
  2. 流暢(卡頓)
  3. 耗損(耗電、流量、網絡)
  4. 安裝包(APK瘦身)

內存優化

由于Android應用的沙箱機制,每個應用所分配的內存大小是有限度的,內存太低就會觸發LMK(Low Memory Killer)機制,進而會出現閃退現象。如果要對內存進行優化,就需要先搞懂java的內存是如何分配和回收的,關于這方面,可以重點參考下面的內容:
Java 垃圾回收器的GC機制,看這一篇就夠了
Android 內存泄漏常見案例及分析
Android應用內存泄漏的定位、分析與解決策略

分析工具

Memory Monitor 工具

Memory Monitor是Android Studio自帶的一個內存監視工具,它可以很好地幫助我們進行內存實時分析。通過點擊Android Studio右下角的Memory Monitor標簽,打開工具可以看見較淺藍色代表free的內存,而深色的部分代表使用的內存從內存變換的走勢圖變換,可以判斷關于內存的使用狀態,例如當內存持續增高時,可能發生內存泄漏;當內存突然減少時,可能發生GC等。

Memory Analyzer工具

MAT 是一個快速,功能豐富的 Java Heap 分析工具,通過分析 Java 進程的內存快照 HPROF 分析,從眾多的對象中分析,快速計算出在內存中對象占用的大小,查看哪些對象不能被垃圾收集器回收,并可以通過視圖直觀地查看可能造成這種結果的對象。

LeakCanary工具

LeakCanary是一個內存監測工具,該工具是Square公司出品的,所謂Square出品必屬精品,LeakCanary的官方地址為https://github.com/square/leakcanar,我們可以在Gradle里引用它。

Android Lint 工具

Android Lint 是Android Sutido種集成的一個Android代碼提示工具,它可以給布局、代碼提供非常強大的幫助。如果在布局文件中寫了三層冗余的LinearLayout布局,就會在編輯器右邊看到提示。當然這個是一個簡單的舉例,Lint的功能非常強大,大家應該養成寫完代碼查看Lint的習慣,這不僅讓你及時發現代碼種隱藏的一些問題,更能讓你養成良好的代碼風格,要知道,這些Lint提示可都是Google大牛們汗水合智慧的結晶。

其他建議

在Android應用開發中,影響穩定性的原因很多,比如內存使用不合理、代碼異常場景考慮不周全、代碼邏輯不合理等,都會對應用的穩定性造成影響。
其中最常見的兩個場景是:Crash 和 ANR,這兩個錯誤將會使得程序無法使用。所以做好Crash監控,把崩潰信息、異常信息收集記錄起來,以便后續分析;合理使用主線程處理業務,不要在主線程中做耗時操作,防止ANR程序無響應發生。
具體可以參考下面的文章鏈接:
Android系統穩定性問題總結

交互優化

交互是與用戶體驗最直接的方面,交互場景大概可以分為四個部分:UI 繪制、應用啟動、頁面跳轉、事件響應。對于上面四個方面,大致可以從以下兩個方面來進行優化:

  • 界面繪制:主要原因是繪制的層級深、頁面復雜、刷新不合理,由于這些原因導致卡頓的場景更多出現在 UI 和啟動后的初始界面以及跳轉到頁面的繪制上。
  • 數據處理:導致這種卡頓場景的原因是數據處理量太大,一般分為三種情況,一是數據在處理 UI 線程,二是數據處理占用 CPU 高,導致主線程拿不到時間片,三是內存增加導致 GC 頻繁,從而引起卡頓。

我們知道,Android的繪制需要經過onMeasure、onLayout、onDraw等幾個步驟,所以布局的層級越深、元素越多、耗時也就越長。還有就是Android 系統每隔 16ms 發出 VSYNC 信號,觸發對 UI 進行渲染,如果每次渲染都成功,這樣就能夠達到流暢的畫面所需的 60FPS。如果某個操作花費的時間是 24ms ,系統在得到 VSYNC 信號時就無法正常進行正常渲染,這樣就發生了丟幀現象。

之所以出現卡頓現象,是因為有兩個原因:

  • 繪制任務太重,繪制一幀內容耗時太長
  • 主線程太忙,根據系統傳遞過來的 VSYNC 信號來時還沒準備好數據導致丟幀

基于問題產生的原因,我們可以從以下幾個方面進行優化:

布局優化

在Android種系統對View進行測量、布局和繪制時,都是通過對View數的遍歷來進行操作的。如果一個View數的高度太高就會嚴重影響測量、布局和繪制的速度。Google也在其API文檔中建議View高度不宜哦過10層。現在版本種Google使用RelativeLayout替代LineraLayout作為默認根布局,目的就是降低LineraLayout嵌套產生布局樹的高度,從而提高UI渲染的效率。
在布局優化方面,我們可以從以下幾個方面進行優化:

  • 布局復用,使用<include>標簽重用layout;
  • 提高顯示速度,使用<ViewStub>延遲View加載;
  • 減少層級,使用<merge>標簽替換父級布局;
  • 注意使用wrap_content,會增加measure計算成本;
  • 刪除控件中無用屬性;

渲染優化

過度繪制是指在屏幕上的某個像素在同一幀的時間內被繪制了多次。在多層次重疊的 UI 結構中,如果不可見的 UI 也在做繪制的操作,就會導致某些像素區域被繪制了多次,從而浪費了多余的 CPU 以及 GPU 資源。我們可以通過開啟手機的過渡繪制功能來檢測頁面是否被過度繪制。

為了避免過度繪制,我們可以從以下幾個方面進行優化:

  • 布局上的優化,移除 XML 中非必須的背景,移除 Window 默認的背景、按需顯示占位背景圖片。
  • 自定義View優化,使用 canvas.clipRect()來幫助系統識別那些可見的區域,只有在這個區域內才會被繪制。

啟動優化

應用一般都有閃屏頁,優化閃屏頁的 UI 布局,可以通過 Profile GPU Rendering 檢測丟幀情況。
也可以通過啟動加載邏輯優化。可以采用分布加載、異步加載、延期加載策略來提高應用啟動速度。
數據準備。數據初始化分析,加載數據可以考慮用線程初始化等策略。

刷新優化

Android開發中,通常是異步操作頁面的,因此需要可以從刷新優化上來優化應用,主要有兩個原則:

  • 減少刷新次數;
  • 縮小刷新區域;

動畫優化

在實現動畫效果時,需要根據不同場景選擇合適的動畫框架來實現。有些情況下,可以用硬件加速方式來提供流暢度。

耗電優化

在移動設備中,電池的重要性不言而喻,沒有電什么都干不成。對于操作系統和設備開發商來說,耗電優化一致沒有停止,去追求更長的待機時間,而對于一款應用來說,并不是可以忽略電量使用問題,特別是那些被歸為“電池殺手”的應用,最終的結果是被卸載。因此,應用開發者在實現需求的同時,需要盡量減少電量的消耗。

在 Android5.0 以前,在應用中測試電量消耗比較麻煩,也不準確,5.0 之后專門引入了一個獲取設備上電量消耗信息的 API,即Battery Historian。Battery Historian 是一款由 Google 提供的 Android 系統電量分析工具,和Systrace 一樣,是一款圖形化數據分析工具,直觀地展示出手機的電量消耗過程,通過輸入電量分析文件,顯示消耗情況,最后提供一些可供參考電量優化的方法。

網絡優化

對于網絡的優化,可以從以下幾個方面著手進行:

圖片網絡優化

例如,針對網絡情況,返回不同的圖片數據,一種是高清大圖,一種是正常圖片,一種是縮略小圖。當用戶處于wifi下給控件設置高清大圖,當4g或者3g模式下加載正常圖片,當弱網條件下加載縮略圖。

網絡數據優化

移動端獲取網絡數據優化可以從以下幾點著手:

  • 連接復用:節省連接建立時間,如開啟 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%左右。

異常攔截優化

在獲取數據的流程中,訪問接口和解析數據時都有可能會出錯,我們可以通過攔截器在這兩層攔截錯誤。

  • 在訪問接口時,我們不用設置攔截器,因為一旦出現錯誤,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 字節碼程序,讓 Dalvik 虛擬機可執行,一般情況下,Android 應用在打包時通過Android SDK 中的 dx 工具將 Java 字節碼轉換為 Dalvik 字節碼。
  • resources.arsc。記錄著資源文件和資源 ID 之間的映射關系,用來根據資源 ID 尋找資源。

基于上面的組成部分,那么優化也可以從以下幾個方面著手:

  • 代碼混淆。使用proGuard 代碼混淆器工具,它包括壓縮、優化、混淆等功能。
  • 資源優化。比如使用 Android Lint 刪除冗余資源,資源文件最少化等。
  • 圖片優化。比如利用 AAPT 工具對 PNG 格式的圖片做壓縮處理,降低圖片色彩位數等。
  • 避免重復功能的庫,使用 WebP圖片格式等。
  • 插件化,比如功能模塊放在服務器上,按需下載,可以減少安裝包大小。
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,739評論 6 534
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,634評論 3 419
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,653評論 0 377
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,063評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,835評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,235評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,315評論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,459評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,000評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,819評論 3 355
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,004評論 1 370
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,560評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,257評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,676評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,937評論 1 288
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,717評論 3 393
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,003評論 2 374

推薦閱讀更多精彩內容