Android:史上最全性能優(yōu)化方案解析
Android中的性能優(yōu)分為以下幾個方面:
布局優(yōu)化
內(nèi)存優(yōu)化
卡頓優(yōu)化
……
在LinearLayout和RelativeLayout都可以完成布局的情況下優(yōu)先選擇LinearLayout,可以減少View的層級,但是注意相同組件可能RelativeLayout繪制時間長
使用 < include > 標(biāo)簽將常用的布局組件共同的部分抽取出來,以便復(fù)用。
通過 < ViewStub > 標(biāo)簽來加載不常用的布局,延遲加載(需要的時候在activity中加載出來)
使用 < Merge > 標(biāo)簽來減少布局的嵌套層次
二.繪制優(yōu)化
繪制優(yōu)化是指View的onDraw方法要避免執(zhí)行大量的操作,這主要體現(xiàn)在兩個方面:
1.onDraw中不要創(chuàng)建新的局部對象。
因為onDraw方法可能會被頻繁調(diào)用,這樣就會在一瞬間產(chǎn)生大量的臨時對象,這不僅占用了過多的內(nèi)存而且還會導(dǎo)致系統(tǒng)更加頻繁gc,降低了程序的執(zhí)行效率。
2.onDraw方法中不要做耗時的任務(wù),
不能執(zhí)行成千上萬次的循環(huán)操作,盡管每次循環(huán)都很輕量級,但是大量的循環(huán)仍然十分搶占CPU的時間片,這會造成View的繪制過程不流暢。
按照Google官方給出的性能優(yōu)化典范中的標(biāo)準(zhǔn),View的繪制頻率保證60fps是最佳的,這就要求每幀繪制時間不超過16ms(16ms = 1000/60),雖然程序很難保證16ms這個時間,但是盡量降低onDraw方法中的復(fù)雜度總是切實有效的。
三.網(wǎng)絡(luò)優(yōu)化
常見的網(wǎng)絡(luò)優(yōu)化方案如下:
盡量減少網(wǎng)絡(luò)請求,能夠合并的就盡量合并
避免DNS解析,根據(jù)域名查詢可能會耗費上百毫秒的時間,也可能存在DNS劫持的風(fēng)險??梢愿鶕?jù)業(yè)務(wù)需求采用增加動態(tài)更新IP的方式,或者在IP方式訪問失敗時切換到域名訪問方式。
大量數(shù)據(jù)的加載采用分頁的方式
網(wǎng)絡(luò)數(shù)據(jù)傳輸采用GZIP壓縮
加入網(wǎng)絡(luò)數(shù)據(jù)的緩存,避免頻繁請求網(wǎng)絡(luò)
上傳圖片時,在必要的時候壓縮圖片
四.安裝包優(yōu)化
安裝包優(yōu)化的核心就是減少apk的體積,常見的方案如下:
減少應(yīng)用中不必要的資源文件,比如圖片,在不影響APP效果的情況下盡量壓縮圖片,有一定的效果
在使用了SO庫的時候優(yōu)先保留v7版本的SO庫,刪掉其他版本的SO庫。原因是在2018年,v7版本的SO庫可以滿足市面上絕大多數(shù)的要求,可能八九年前的手機(jī)滿足不了,但我們也沒必要去適配老掉牙的手機(jī)。實際開發(fā)中減少apk體積的效果是十分顯著的,如果你使用了很多SO庫,比方說一個版本的SO庫一共10M,那么只保留v7版本,刪掉armeabi和v8版本的SO庫,一共可以減少20M的體積。
res資源優(yōu)化
(1)只使用一套圖片,使用高分辨率的圖片。
(2)UI設(shè)計在ps安裝TinyPNG插件,對圖片進(jìn)行無損壓縮。
(3)svg圖片:一些圖片的描述,犧牲CPU的計算能力的,節(jié)省空間。使用的原則:簡單的圖標(biāo)。
(4)圖片使用WebP(https://developers.google.com/speed/webp/)的格式(Facebook、騰訊、淘寶在用。)缺點:加載相比于PNG要慢很多。但是配置比較高。工具:http://isparta.github.io/
(5)使用tintcolor(android - Change drawable color programmatically)實現(xiàn)按鈕反選效果。
代碼優(yōu)化
(1)實現(xiàn)功能模塊的邏輯簡化
(2)Lint工具檢查無用文件將無用的資源列在“UnusedResources: Unused resources”,刪除。
(3)移除無用的依賴庫。
lib資源優(yōu)化
(1)動態(tài)下載的資源。
(2)一些模塊的插件化動態(tài)添加。
(3)so文件的剪裁和壓縮。
assets資源優(yōu)化
(1)音頻文件最好使用有損壓縮的格式,比如采用opus、mp3等格式,但是最好不要使用無損壓縮的音樂格式
(2)對ttf字體文件壓縮,可以采用FontCreator工具只提取出你需要的文字。比如在做日期顯示時,其實只需要數(shù)字字體,但是使用原有的字體庫可能需要10MB大小,如果只是把你需要的字體提取出來生成的字體文件只有10KB
代碼混淆。
使用proGuard 代碼混淆器工具,它包括壓縮、優(yōu)化、混淆等功能。
插件化
可將功能模塊放服務(wù)器,需要用時再加載。
7z極限壓縮
五.Android內(nèi)存優(yōu)化
1.Android內(nèi)存管理機(jī)制
Android應(yīng)用都是在Android虛擬機(jī)上運(yùn)行的,內(nèi)存分配和垃圾回收都是由Android虛擬機(jī)來完成的。
2.常見的內(nèi)存泄漏
其實內(nèi)存泄漏的本質(zhì)就是較長生命周期的對象引用了較短生命周期的對象。
2.1 內(nèi)存泄露
內(nèi)存泄漏原因:堆上分配的對象已經(jīng)不會再使用,但是GC收集器無法對其進(jìn)行回收,此對象被強(qiáng)應(yīng)用所引用 。
靜態(tài)變量導(dǎo)致的內(nèi)存泄漏
解決辦法:將內(nèi)部類設(shè)為靜態(tài)內(nèi)部類或獨立出來;使用context.getApplicationContext()。
單例模式導(dǎo)致的內(nèi)存泄漏
解決辦法:傳參context.getApplicationContext()。
屬性動畫導(dǎo)致的內(nèi)存泄漏
解決辦法:在Activity.onDestroy()中調(diào)用Animator.cancel()停止動畫。
Handler導(dǎo)致的內(nèi)存泄漏
解決辦法:使用靜態(tài)內(nèi)部類+WeakReference弱引用;當(dāng)外部類結(jié)束生命周期時清空消息隊列。
線程導(dǎo)致的內(nèi)存泄漏
解決辦法:將AsyncTask和Runnable設(shè)為靜態(tài)內(nèi)部類或獨立出來;在線程內(nèi)部采用弱引用保存Context引用。
資源未關(guān)閉導(dǎo)致的內(nèi)存泄漏
解決辦法:在Activity銷毀的時候要及時關(guān)閉或者注銷。例如:
① BraodcastReceiver:調(diào)用unregisterReceiver()注銷;
②Cursor,Stream、File:調(diào)用close()關(guān)閉;
③Bitmap:調(diào)用recycle()釋放內(nèi)存(2.3版本后無需手動)。
Adapter導(dǎo)致的內(nèi)存泄漏
詳情:不使用緩存而只依靠getView() 每次重新實例化Item,會給gc制造壓力。
解決辦法:在構(gòu)造Adapter時使用緩存的convertView。
WebView導(dǎo)致的內(nèi)存泄漏。
詳情:WebView比較特殊,即使是調(diào)用了它的destroy方法,依然會導(dǎo)致內(nèi)存泄漏。
解決辦法:其實避免WebView導(dǎo)致內(nèi)存泄漏的最好方法就是讓W(xué)ebView所在的Activity處于另一個進(jìn)程中,當(dāng)這個Activity結(jié)束時殺死當(dāng)前WebView所處的進(jìn)程即可,我記得阿里釘釘?shù)腤ebView就是另外開啟的一個進(jìn)程,應(yīng)該也是采用這種方法避免內(nèi)存泄漏。
集合類泄漏
詳情:比如全局map等有靜態(tài)應(yīng)用,最后沒有做刪除。
解決辦法:在onDestry時回收不需要的集合。
2.2 擴(kuò)大內(nèi)存
大廠的SDK可能內(nèi)存泄漏會少一些,但一些小廠的SDK質(zhì)量也就不太靠譜一些。那應(yīng)對這種我們無法改變的情況,最好的辦法就是擴(kuò)大內(nèi)存。
擴(kuò)大內(nèi)存通常有兩種方法:
一個是在清單文件中的Application下添加largeHeap="true"這個屬性,另一個就是同一個應(yīng)用開啟多個進(jìn)程來擴(kuò)大一個應(yīng)用的總內(nèi)存空間。
第二種方法其實就很常見了,比方說我使用過個推的SDK,個推的Service其實就是處在另外一個單獨的進(jìn)程中。
Android中的內(nèi)存優(yōu)化總的來說就是開源和節(jié)流,開源就是擴(kuò)大內(nèi)存,節(jié)流就是避免內(nèi)存泄漏。
2.3 檢測、分析內(nèi)存泄漏的工具
MemoryMonitor:隨時間變化,內(nèi)存占用的變化情況
MAT:輸入HRPOF文件,輸出分析結(jié)果
a. Histogram:查看不同類型對象及其大小
b.DominateTree:對象占用內(nèi)存及其引用關(guān)系
c.MAT使用教程
LeakCanary:實時監(jiān)測內(nèi)存泄漏的庫(LeakCanary原理)
六.卡頓優(yōu)化方案
不要在主線程進(jìn)行網(wǎng)絡(luò)訪問/大文件的IO操作
繪制UI時,盡量減少繪制UI層次;減少不必要的view嵌套,可以用Hierarchy Viewer工具來檢測,后面會詳細(xì)講;
當(dāng)我們的布局是用的FrameLayout的時候,我們可以把它改成merge,可以避免自己的幀布局和系統(tǒng)的ContentFrameLayout幀布局重疊造成重復(fù)計算(measure和layout)
提高顯示速度,使用ViewStub:當(dāng)加載的時候才會占用。不加載的時候就是隱藏的,僅僅占用位置。
在view層級相同的情況下,盡量使用 LinerLayout而不是RelativeLayout;因為RelativeLayout在測量的時候會測量二次,而LinerLayout測量一次,可以看下它們的源碼;
刪除控件中無用的屬性;
布局復(fù)用.比如listView 布局復(fù)用
盡量避免過度繪制(overdraw),比如:背景經(jīng)常容易造成過度繪制。由于我們布局設(shè)置了背景,同時用到的MaterialDesign的主題會默認(rèn)給一個背景。這時應(yīng)該把主題添加的背景去掉;還有移除
XML 中非必須的背景
自定義View優(yōu)化。使用 canvas.clipRect()來幫助系統(tǒng)識別那些可見的區(qū)域,只有在這個區(qū)域內(nèi)才會被繪制。也是避免過度繪制.
啟動優(yōu)化,啟動速度的監(jiān)控,發(fā)現(xiàn)影響啟動速度的問題所在,優(yōu)化啟動邏輯,提高應(yīng)用的啟動速度。比如閃屏頁面,合理優(yōu)化布局,加載邏輯優(yōu)化,數(shù)據(jù)準(zhǔn)備.
合理的刷新機(jī)制,盡量減少刷新次數(shù),盡量避免后臺有高的 CPU 線程運(yùn)行,縮小刷新區(qū)域。
七.耗電優(yōu)化
耗電的原因其實很多,這里我就講一下幾種優(yōu)化方案,優(yōu)化方案的反面就是他的原因了,幾種優(yōu)化方案如下:
合理的使用wake_lock鎖,wake_lock鎖主要是相對系統(tǒng)的休眠(這里就是為了省電,才做休)而言的,意思就是我的程序給CPU加了這個鎖那系統(tǒng)就不會休眠了,這樣做的目的是為了全力配合我們程序的運(yùn)行。有的情況如果不這么做就會出現(xiàn)一些問題,比如微信等及時通訊的心跳包會在熄屏不久后停止網(wǎng)絡(luò)訪問等問題。所以微信里面是有大量使用到了wake_lock鎖。
使用jobScheduler2,集中處理一些網(wǎng)絡(luò)請求,有些不用很及時的處理可以放在充電的時候處理,比如,圖片的處理,APP下載更新等等;
計算優(yōu)化,避開浮點運(yùn)算等。
數(shù)據(jù)在網(wǎng)絡(luò)上傳輸時,盡量壓縮數(shù)據(jù)后再傳輸,建議用FlatBuffer序列化技術(shù),這個比json效率高很多倍,不了解FlatBuffer,建議找資料學(xué)習(xí)一下。
針對“性能優(yōu)化”這個要點,分享給大家一份《360°全方位Android性能優(yōu)化解析》,這份學(xué)習(xí)手冊將會帶領(lǐng)大家一步一步深入探索Android的性能優(yōu)化,讓產(chǎn)品的性能從各個方面得到提升,希望大家喜歡。
這份資料一共有721頁,4個大點,25個小章節(jié),不僅僅有詳細(xì)的底層原理的解析,還有專門的實踐案例!
掃碼即可領(lǐng)取資料
第一章 設(shè)計思想與代碼質(zhì)量優(yōu)化
1.六大原則
單一職責(zé)原則
里氏替換原則
依賴倒轉(zhuǎn)原則
接口隔離原則
……
2.設(shè)計模式
結(jié)構(gòu)型模式:橋接模式、適配器模式、裝飾器模式、代理模式、門面(外觀)模式……
創(chuàng)建型模式:建造者模式、單例模式、抽象工廠模式、工廠方法模式……
數(shù)據(jù)結(jié)構(gòu):數(shù)組、棧、隊列、鏈表、樹……
算法:排序算法、查找算法……
第二章 程序性能優(yōu)化
1.啟動速度與執(zhí)行效率優(yōu)化
冷啟動和熱啟動解析
APP 啟動黑白屏解決辦法
APP 卡頓問題分析及解決方案
啟動速度與執(zhí)行效率優(yōu)化之 StrictMode
……
2.布局檢測與優(yōu)化
布局層級優(yōu)化
過度渲染
……
3.內(nèi)存優(yōu)化
內(nèi)存抖動和內(nèi)存泄漏
內(nèi)存大戶
Bitmap 內(nèi)存優(yōu)化
Profile 內(nèi)存監(jiān)測工具
Mat 大對象與泄漏檢測
耗電優(yōu)化
網(wǎng)絡(luò)傳輸與數(shù)據(jù)存儲優(yōu)化網(wǎng)絡(luò)傳輸與數(shù)據(jù)存儲優(yōu)化
APK 大小優(yōu)化
屏幕適配
……
4.耗電優(yōu)化
Doze&Standby
Battery Historian
JobScheduler
WorkManager
5.網(wǎng)絡(luò)傳輸與數(shù)據(jù)存儲優(yōu)化
google 序列化工具 protobuf
7z 極限壓縮
……
6.APK 大小優(yōu)化
APK 瘦身
微信資源混淆原理
……
7.屏幕適配
進(jìn)行適配的原理
屏幕分辨率限定符與 smallestWidth 限定符適配原理
為什么選擇 smallestWidth 限定符適配
怎么適配其他 module
常見問題處理
……
8.OOM 問題原理解析
adj 內(nèi)存管理機(jī)制
JVM 內(nèi)存回收機(jī)制與 GC 算法解析
生命周期相關(guān)問題總結(jié)
Bitmap 壓縮方案總結(jié)
……
9.ANR 問題解析
AMS 系統(tǒng)時間調(diào)節(jié)原理
程序等待原理分析
ANR 問題解決方案
……
10.Crash 監(jiān)控方案
Java 層監(jiān)控方案
Nativie 層監(jiān)控方案
……
第三章 開發(fā)效率優(yōu)化
分布式版本控制系統(tǒng) Git
企業(yè)高效持續(xù)集成平臺場景介紹
GIT 分布式版本控制系統(tǒng)
GIT 分支管理
……
2.自動化構(gòu)建系統(tǒng) Gradle:
Gradle 與 Android 插件:gradle 與 android gradle 插件的關(guān)系、Gradle Transform API 的基本使用……
Gradle Transform API 的基本使用:什么是 Transform、Transform 的使用場景、Transform API 學(xué)習(xí)、輸入的類型……
自定義插件開發(fā):Gradle 插件簡介、開始準(zhǔn)備、實踐、自定義 Gradle 插件、buildSrc 模塊方式……
插件實戰(zhàn):多渠道打包、發(fā)版自動釘釘……
掃碼即可領(lǐng)取資料
第四章 APP 性能優(yōu)化實踐
1.啟動速度
應(yīng)用啟動的一般流程
冷啟動和熱啟動
啟動速度的測量
啟動窗口優(yōu)化
線程優(yōu)化
系統(tǒng)調(diào)度優(yōu)化
GC 優(yōu)化
IO 優(yōu)化
資源重排
主頁布局優(yōu)化
類加載優(yōu)化
選擇合適的啟動框架
減少 Activity 的跳轉(zhuǎn)層次
廠商優(yōu)化
后臺?;?/p>
……

2.流暢度
性能問題分析的一些工具和套路
通過性能數(shù)據(jù)數(shù)據(jù)分析
Android 平臺性能導(dǎo)致的性能案例
Android App 自身導(dǎo)致的性能問題
低內(nèi)存的數(shù)據(jù)特征和行為特征
應(yīng)用寶
訊飛輸入法無障礙服務(wù)導(dǎo)致的整機(jī)卡頓分析
字節(jié)跳動:今日頭條圖文詳情頁秒開實踐
……
3.抖音在 APK 包大小資源優(yōu)化的實踐
圖片壓縮
webp 無侵入式兼容
多 DPI 優(yōu)化
重復(fù)資源合并
shrinkResource 嚴(yán)格模式
資源混淆(兼容 aab 模式)
ARSC 瘦身
……
4.優(yōu)酷響應(yīng)式布局技術(shù)全解析
優(yōu)酷APP響應(yīng)式布局技術(shù)概述
優(yōu)酷APP響應(yīng)式布局Android落地
在分發(fā)場景的落地
在消費場景的落地
優(yōu)酷APP響應(yīng)式布局之測試方案
……
5.網(wǎng)絡(luò)優(yōu)化
手機(jī)淘寶在網(wǎng)絡(luò)的鏈路優(yōu)化
百度 APP 在網(wǎng)絡(luò)深度優(yōu)化的實踐
……
6.手機(jī)淘寶雙十一性能優(yōu)化項目揭秘
一秒法則的實現(xiàn)
啟動時間和頁面幀率提升 20%
Android 手機(jī)內(nèi)存節(jié)省50%
……
7.高德 APP 全鏈路源碼依賴分析
高德 APP 平臺架構(gòu)
基礎(chǔ)實現(xiàn)原理
項目架構(gòu)
應(yīng)用場景及實現(xiàn)原理
……
8.徹底干掉OOM的實戰(zhàn)經(jīng)驗分享
排查內(nèi)存泄漏
兜底策略
內(nèi)存峰值太高
特大圖排查優(yōu)化
……
9.微信 Android終端內(nèi)存優(yōu)化實踐
Activity 泄露檢測
Bitmap 分配及回收追蹤
Native 內(nèi)存泄漏檢測
線程監(jiān)控
內(nèi)存監(jiān)控
……
總結(jié)
性能優(yōu)化不是更新一兩個版本就可以解決的,是持續(xù)性的需求,持續(xù)集成迭代反饋。在實際的項目中,在項目剛開始的時候,由于人力和項目完成時間限制,性能優(yōu)化的優(yōu)先級比較低,等進(jìn)入項目投入使用階段,就需要把優(yōu)先級提高,但在項目初期,在設(shè)計架構(gòu)方案時,性能優(yōu)化的點也需要提早考慮進(jìn)去,這就體現(xiàn)出一個程序員的技術(shù)功底了。
掃碼即可領(lǐng)取資料
