- 做開發(fā)除了實(shí)現(xiàn)功能涨缚,還要注重優(yōu)化,性能優(yōu)化包括的東西還是非常多的策治,包體大小脓魏、啟動(dòng)速度、內(nèi)存通惫、數(shù)據(jù)結(jié)構(gòu)茂翔、ANR、卡頓等等履腋。
- 用戶都希望APP按下珊燎,就能馬上進(jìn)入首頁使用,手機(jī)性能很重要遵湖,但不能要求用戶換手機(jī)悔政,于是我們就需要APP想辦法優(yōu)化啟動(dòng)的速度,不然這APP可能會(huì)被刪掉奄侠。
- Android性能優(yōu)化 - 卡頓和布局優(yōu)化 可以一起學(xué)習(xí)卓箫。
1.啟動(dòng)的狀態(tài)
- 我們APP不是微信那種體量,所以幾乎不可能有廠商給我們搞特殊垄潮,一直掛在那烹卒,大多數(shù)情況下都是冷啟動(dòng)闷盔,優(yōu)化也是主要優(yōu)化冷啟動(dòng)。
-
冷啟動(dòng)
冷啟動(dòng)是指應(yīng)用從頭開始啟動(dòng):系統(tǒng)進(jìn)程在冷啟動(dòng)后才創(chuàng)建應(yīng)用進(jìn)程旅急。發(fā)生冷啟動(dòng)的情況包括應(yīng)用自設(shè)備啟動(dòng)后或系統(tǒng)終止應(yīng)用后首次啟動(dòng)逢勾。 -
熱啟動(dòng)
在熱啟動(dòng)中,系統(tǒng)的所有工作就是將 Activity 帶到前臺(tái)藐吮。只要應(yīng)用的所有 Activity 仍駐留在內(nèi)存中溺拱,應(yīng)用就不必重復(fù)執(zhí)行對(duì)象初始化、布局加載和繪制谣辞。比如回到桌面迫摔,不殺掉APP的時(shí)間內(nèi)又回來。 -
溫啟動(dòng)
溫啟動(dòng)包含了在冷啟動(dòng)期間發(fā)生的部分操作泥从;同時(shí)句占,它的開銷要比熱啟動(dòng)高。有許多潛在狀態(tài)可視
為溫啟動(dòng)躯嫉。例如:
1.用戶在退出應(yīng)用后又重新啟動(dòng)應(yīng)用纱烘。進(jìn)程可能未被銷毀,繼續(xù)運(yùn)行祈餐,但應(yīng)用需要執(zhí)行
onCreate() 從頭開始重新創(chuàng)建 Activity擂啥。
2.系統(tǒng)將應(yīng)用從內(nèi)存中釋放,然后用戶又重新啟動(dòng)它帆阳。進(jìn)程和 Activity 需要重啟哺壶,但傳遞到
onCreate() 的已保存的實(shí)例 state bundle 對(duì)于完成此任務(wù)有一定助益。
2.冷啟動(dòng)耗時(shí)
- 2-5-8原則:
- 當(dāng)用戶能夠在2秒以內(nèi)得到響應(yīng)時(shí)蜒谤,會(huì)感覺系統(tǒng)的響應(yīng)很快变骡;
- 當(dāng)用戶在2-5秒之間得到響應(yīng)時(shí),會(huì)感覺系統(tǒng)的響應(yīng)速度還可以芭逝;
- 當(dāng)用戶在5-8秒以內(nèi)得到響應(yīng)時(shí),會(huì)感覺系統(tǒng)的響應(yīng)速度很慢渊胸,但是還可以接受旬盯;
- 而當(dāng)用戶在超過8秒后仍然無法得到響應(yīng)時(shí),會(huì)感覺系統(tǒng)糟透了翎猛,或者認(rèn)為系統(tǒng)已經(jīng)失去響應(yīng)胖翰。
2.1 系統(tǒng)日志統(tǒng)計(jì)
- 在Logcat,篩選 Displayed切厘,就能看到啟動(dòng)時(shí)長(zhǎng)萨咳。
-
這個(gè)時(shí)長(zhǎng)就是應(yīng)用啟動(dòng)到顯示對(duì)應(yīng)的Activity繪制完成的時(shí)長(zhǎng)。(下圖就是啟動(dòng)到MainActivity)
日志查看啟動(dòng)時(shí)長(zhǎng)
2.2 adb命令統(tǒng)計(jì)
-
adb需要配置環(huán)境變量疫稿,只需要把 sdk 目錄下的 platform-tools 路徑添加到 環(huán)境變量path 里面就行培他。
配置adb環(huán)境變量 adb shell
am shart -S -W com.bao.myapplication/.MainActivity
根據(jù)自己的包名和要啟動(dòng)的Activity輸入這兩行命令就可以看到啟動(dòng)時(shí)間鹃两。
-
TotalTime就是啟動(dòng)時(shí)長(zhǎng)啦。
adb查看啟動(dòng)時(shí)長(zhǎng)
3.啟動(dòng)分析
- 工具詳情可以查看官方文檔:使用 CPU 性能剖析器檢查 CPU 活動(dòng)舀凛。
在這里插入圖片描述
3.1 CPU Profile工具簡(jiǎn)單教程
Android Studio 功能越來越完善俊扳,我們可以利用 CPU Profile 來查看分析啟動(dòng)時(shí)做了什么事情。
-
點(diǎn)擊 app -> Edit Configurations猛遍。
cpu profile Profilling -> Start recording CPU activity on startup馋记。
-
選擇CPU記錄配置 Trace Java Methods。
選擇CPU記錄配置 這四種模式官方文檔也有詳細(xì)說明懊烤。
1.對(duì) Java 方法采樣:在應(yīng)用的 Java 代碼執(zhí)行期間梯醒,頻繁捕獲應(yīng)用的調(diào)用堆棧。分析器會(huì)比較捕獲的數(shù)據(jù)集腌紧,以推導(dǎo)與應(yīng)用的 Java 代碼執(zhí)行有關(guān)的時(shí)間和資源使用信息茸习。
基于采樣的跟蹤存在一個(gè)固有的問題,那就是如果應(yīng)用在捕獲調(diào)用堆棧后進(jìn)入一個(gè)方法并在下次捕獲前退出該方法寄啼,分析器將不會(huì)記錄該方法調(diào)用逮光。如果您想要跟蹤生命周期如此短的方法,應(yīng)使用插樁跟蹤墩划。2.跟蹤 Java 方法:在運(yùn)行時(shí)檢測(cè)應(yīng)用涕刚,從而在每個(gè)方法調(diào)用開始和結(jié)束時(shí)記錄一個(gè)時(shí)間戳。系統(tǒng)會(huì)收集并比較這些時(shí)間戳乙帮,以生成方法跟蹤數(shù)據(jù)杜漠,包括時(shí)間信息和 CPU 使用率。
請(qǐng)注意察净,與檢測(cè)每個(gè)方法相關(guān)的開銷會(huì)影響運(yùn)行時(shí)性能驾茴,并且可能會(huì)影響分析數(shù)據(jù);對(duì)于生命周期相對(duì)較短的方法氢卡,這一點(diǎn)更為明顯锈至。此外,如果應(yīng)用在短時(shí)間內(nèi)執(zhí)行大量方法译秦,則分析器可能很快就會(huì)超出其文件大小限制峡捡,因而不能再記錄更多跟蹤數(shù)據(jù)。3.對(duì) C/C++ 函數(shù)采樣:捕獲應(yīng)用的原生線程的采樣跟蹤數(shù)據(jù)筑悴。如需使用此配置们拙,您必須將應(yīng)用部署到搭載 Android 7.0(API 級(jí)別 24)或更高版本的設(shè)備上。
在內(nèi)部阁吝,此配置使用 simpleperf 跟蹤應(yīng)用的原生代碼砚婆。如果需為 simpleperf 指定其他選項(xiàng),如對(duì)特定設(shè)備 CPU 采樣或指定高精度采樣持續(xù)時(shí)間突勇,您可以從命令行使用 simpleperf装盯。-
4.跟蹤系統(tǒng)調(diào)用:捕獲非常翔實(shí)的細(xì)節(jié)坷虑,以便您檢查應(yīng)用與系統(tǒng)資源的交互情況。您可以檢查線程狀態(tài)的確切時(shí)間和持續(xù)時(shí)間验夯、直觀地查看所有內(nèi)核的 CPU 瓶頸在何處猖吴,并添加需分析的自定義跟蹤事件。當(dāng)您排查性能問題時(shí)挥转,此類信息至關(guān)重要海蔽。如需使用此配置,您必須將應(yīng)用部署到搭載 Android 7.0(API 級(jí)別 24)或更高版本的設(shè)備上绑谣。
使用此跟蹤配置時(shí)党窜,您可以通過檢測(cè)代碼,在分析器時(shí)間軸上直觀地標(biāo)記重要的代碼例程借宵。如需檢測(cè) C/C++ 代碼幌衣,請(qǐng)使用由 trace.h 提供的原生跟蹤 API。如需檢測(cè) Java 代碼壤玫,請(qǐng)使用 Trace 類豁护。如需了解詳情,請(qǐng)參閱檢測(cè)您的應(yīng)用代碼欲间。此跟蹤配置建立在 systrace 的基礎(chǔ)之上楚里。您可以使用 systrace 命令行實(shí)用程序指定除 CPU 性能剖析器提供的選項(xiàng)之外的其他選項(xiàng)。systrace 提供的其他系統(tǒng)級(jí)數(shù)據(jù)可幫助您檢查原生系統(tǒng)進(jìn)程并排查丟幀或幀延遲問題猎贴。
-
設(shè)置好了之后就啟動(dòng)Profile班缎。
啟動(dòng)Profile -
當(dāng)你看到自己APP,CPU的使用率比較低的時(shí)候她渴,差不多就是啟動(dòng)完成了达址,點(diǎn)一下stop。
在這里插入圖片描述
3.2 啟動(dòng)耗時(shí)分析
-
Call Chart 雙擊要看的線程趁耗,就能看到從上到下沉唠,方法執(zhí)行的時(shí)長(zhǎng),除了系統(tǒng)的方法苛败,綠色是自己的代碼右冻,就能看到耗時(shí)了,這里的方法是按時(shí)間線排列的著拭,從啟動(dòng)到完成的過程。
Call Chart -
Top Down標(biāo)簽顯示一個(gè)調(diào)用列表牍帚,在該列表中展開方法或函數(shù)節(jié)點(diǎn)會(huì)顯示它的被調(diào)用方儡遮。下圖可以看到我在自定義View里面放了一個(gè)Thread.sleep,休眠了3秒。
Top Down -
Flame Chart火焰圖橫向代表方法時(shí)長(zhǎng)暗赶,向上就是被調(diào)用的方法鄙币,我們也能看到自定義View里面的sleep明顯比其他長(zhǎng)肃叶。
Flame Chart
3.3 使用Debug Api 生成.trace文件
- 在Application onCreate 方法加入 Debug.startMethodTracing()。
- 在MainActivitu onWindowFocusChanged(boolean hasFocus) 方法加入 Debug.stopMethodTracing()十嘿。
public class BaoApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
Debug.startMethodTracing("baoTest");
}
}
public class MainActivity extends AppCompatActivity {
.
.
.
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
.
.
.
}
/**
* MainActivity 停止啟動(dòng)分析的地方
* @param hasFocus
*/
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
Debug.stopMethodTracing();
}
}
- 默認(rèn)在自己應(yīng)用的目錄下生成 .trace 文件因惭,復(fù)制到自己電腦目錄下。
.trace文件目錄 -
拖到Android Studio绩衷,就可以查看結(jié)果了蹦魔。
拖進(jìn)去分析
4.StrictMode嚴(yán)苛模式
- 開發(fā)時(shí)開啟嚴(yán)苛模式,提示我們咳燕。
@Override
public void onCreate() {
super.onCreate();
if (BuildConfig.DEBUG) {
//線程檢測(cè)
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
.detectDiskReads()
.detectDiskWrites()
.detectNetwork()
.penaltyLog()
.build());
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
.detectLeakedSqlLiteObjects()//數(shù)據(jù)庫對(duì)象泄漏
.detectLeakedClosableObjects()//未關(guān)閉的對(duì)象泄漏
.penaltyDeath()//違規(guī)奔潰
.penaltyLog()//違規(guī)日志
.build());
}
}
5.結(jié)尾
- 簡(jiǎn)化布局勿决,布局層級(jí)不要太多可以提高啟動(dòng)速度(熟練使用約束布局可以減少層級(jí)),啟動(dòng)和主線程不要做耗時(shí)操作招盲。
- 啟動(dòng)盡量別搞什么sleep休眠之類的低缩,就算不報(bào)錯(cuò),但也不好查找曹货。
- 有的APP會(huì)有啟動(dòng)廣告咆繁,我們可以在展示廣告的時(shí)間里,利用子線程繼續(xù)初始化工作顶籽。
- 啟動(dòng)的流程非常的多玩般,也非常復(fù)雜,一般我們能改的就是自己的APP蜕衡,通過工具分析自己的APP哪些地方比較耗時(shí)壤短,能減少的盡量減少,有一些減少非常有限慨仿,但是項(xiàng)目比較大的時(shí)候久脯,往往都是積少成多的,需要一點(diǎn)點(diǎn)去優(yōu)化镰吆。