1App啟動(dòng)優(yōu)化介紹
背景介紹
第一體驗(yàn) :八秒定律
啟動(dòng)分類
1冷啟動(dòng)
耗時(shí)最多柱徙、衡量標(biāo)準(zhǔn)
幫助尋找優(yōu)化方向
2熱啟動(dòng)
最快
后臺(tái)--》前臺(tái)
3溫啟動(dòng)
較快
重走LifeCycle 而不會(huì)重走Application荡碾、進(jìn)程等的創(chuàng)建
相關(guān)任務(wù)
冷啟動(dòng)之前:
啟動(dòng)APP
加載空白Window
創(chuàng)建進(jìn)程
隨后任務(wù):
創(chuàng)建Application
啟動(dòng)主線程
創(chuàng)建MainActivity
加載布局
布置屏幕
首幀繪制
優(yōu)化方向
Application和Activity生命周期階段
2App啟動(dòng)時(shí)間測(cè)量方式
adb命令
adb shell am start -W packagename/packagename.首屏Activity
ThisTime:最后Activity啟動(dòng)耗時(shí)
TotalTime:所有Activity啟動(dòng)耗時(shí)
WaitTime:Ams啟動(dòng)Activity總耗時(shí)
線下方便,不能帶到線上;
非嚴(yán)謹(jǐn)黔夭、精確
手動(dòng)打點(diǎn)
啟動(dòng)時(shí)埋點(diǎn)帽哑,結(jié)束時(shí)埋點(diǎn),二者差值
開始計(jì)時(shí):
在“attachBaseContext()”里調(diào)用7乇取芦鳍!
結(jié)束計(jì)時(shí):
誤區(qū):onWindowFocusChanged只是首幀時(shí)間,首次繪制
正確:真實(shí)數(shù)據(jù)展示葛账,數(shù)據(jù)資料繪制的第一條展示柠衅。
精確,可帶到線上籍琳,推薦使用菲宴。
避開誤區(qū),采用第一條數(shù)據(jù)展示
addOnDrawListener要求API16 趋急,替換為addPreDrawListener喝峦。
3App啟動(dòng)優(yōu)化工具選擇
traceview、systrace 兩種方式互相補(bǔ)充
1traceview
圖形的形式展示執(zhí)行時(shí)間宣谈、調(diào)用棧等
信息全面愈犹,包含所有線程
使用方式
//開始
Debug.startMethodTracing("文件名1")
//結(jié)束
Debug.stopMethodTracing()
生成文件在SD卡:Android/data/packagename/files/文件名1.trace
traceview其實(shí)默認(rèn)有一個(gè)最大限制8M,可在方法里參數(shù)指定闻丑。
文件名1.trace 打開
Top Down:
函數(shù)的調(diào)用表漩怎,逐級(jí)調(diào)用
cpu真正花在上面的時(shí)間
Call Chart:
Bottom UP 是Top Down 的反向即誰調(diào)用了我。
另一個(gè)Flame不常用
總結(jié):
運(yùn)行時(shí)開銷嚴(yán)重嗦嗡,整體都會(huì)變慢
可能會(huì)帶偏優(yōu)化方向勋锤。
traceview (可在代碼中埋點(diǎn))
2systrace
結(jié)合Android 內(nèi)核的數(shù)據(jù)生成Html報(bào)告
API18以上,之下推薦TraceCompat
使用方式
起點(diǎn):
結(jié)束:
[圖片上傳中...(12.png-7eb89d-1615694063053-0)]
總結(jié):
輕量級(jí)侥祭,開銷小 叁执,埋在哪做哪茄厘,TraceView都做
直接反映CPU利用率
CPUtime與walltime區(qū)別:我們要優(yōu)化的是CPUtime,是CPU真正花在上面的時(shí)間
為什么二者時(shí)間不一樣:鎖沖突谈宛。
4優(yōu)雅獲取耗時(shí)
常規(guī)方式
背景:需要知道啟動(dòng)階段所有方法耗時(shí)
實(shí)現(xiàn):手動(dòng)埋點(diǎn)
統(tǒng)計(jì)每個(gè)方法耗時(shí)的話會(huì)非常丑陋次哈,會(huì)導(dǎo)致強(qiáng)耦合。
侵入性強(qiáng)
工作量大
*SystemClock.curretThreadMillis();就是CPU時(shí)間
AOP(Aspect Oriented Programming)面向切面編程 介紹
針對(duì)同一類問題的統(tǒng)一處理:性能問題
無需入侵代碼
AspectJ使用
AOP相關(guān)知識(shí)點(diǎn)
AOP實(shí)戰(zhàn)
修改一下代碼:
我們沒有在原來代碼上操作吆录,只是加入了一個(gè)類窑滞,非常優(yōu)雅。
無侵入性恢筝;
修改方便哀卫;
5異步優(yōu)化詳解
優(yōu)化技巧
Theme 切換(首屏、閃屏):感官上的快
drawable下創(chuàng)建文件:
異步優(yōu)化實(shí)戰(zhàn)
核心思想:子線程分擔(dān)主線程任務(wù)撬槽,并行減少時(shí)間
主線程一個(gè)在工作此改,手機(jī)為多核。有的廠家只分配一個(gè)侄柔。
使用線程池:
啟動(dòng)階段最好不做new線程操作:1粗放共啃;2可能導(dǎo)致內(nèi)存泄漏;3不能復(fù)用
參考AsyncTask獲取CPU數(shù)量
private final int CPU_COUNT=Runtime.getRuntine().availableProcessors();
private final int CORE_POOL_SIZE = Math.max(2,Math.min(CPU_COUNT-1),4);
ExecutorService service =Executors.newFixedThreadPool(CORE_POOL_SIZE );
service.submin(new Runnable(){
@Override
public void run(){
//Bugly
initBugly();
}
});
service.submin(new Runnable(){
@Override
public void run(){
//友盟
initUmeng();
}
});
....
*可不可以都放在一個(gè)Runnable里呢勋拟?
可以勋磕,但是不好。如果比如new了三個(gè)線程只用了一個(gè)敢靡,等于資源浪費(fèi)挂滓。
*可不可以方法都用子線程呢?
不可以啸胧。
代碼并不滿足異步需求赶站。此部分必須放在 主線程中。
代碼有先后順序的纺念,
解決辦法CountDownLatch:
private CountDownLatch mCountDownLatch =new CountDownLatch(1);//滿足一次
onCreate(){
service.submin(new Runnable(){
@Override
public void run(){
//友盟
initUmeng();
mCountDownLatch.countDown();//滿足了一次
}
});
.......
//Create結(jié)束時(shí)調(diào)用
try{
mCountDownLatch.await();//檢測(cè)條件贝椿,如果次數(shù)不夠就在此等待
}catch(InterruptedException e){
e.printStackTrace();
}
}
6異步初始化最優(yōu)解---啟動(dòng)器
常規(guī)異步痛點(diǎn)
1代碼不優(yōu)雅;
2存在依賴關(guān)系的不好處理陷谱。雖然可以像下面這樣放一起:
3不方便統(tǒng)計(jì)烙博。維護(hù)成本高。
啟動(dòng)器介紹
核心思想:充分利用CPU多核烟逊,自動(dòng)梳理啟動(dòng)順序渣窜。
1代碼Task化,啟動(dòng)邏輯抽象成Task宪躯。
2根據(jù)所有任務(wù)依賴關(guān)系排序生成一個(gè)有向無環(huán)圖乔宿。
3多線程按照排序后的優(yōu)先級(jí)依次執(zhí)行。
啟動(dòng)器實(shí)戰(zhàn)
APP性能優(yōu)化系列-自定義啟動(dòng)器
https://blog.csdn.net/augfun/article/details/109703739?utm_medium=distribute.pc_relevant.none-task-blog-baidujs_baidulandingword-1&spm=1001.2101.3001.4242
7更優(yōu)的初始化延遲方案
常規(guī)方案
New Handler().postDelayed
Feed顯示之后調(diào)用
時(shí)機(jī)不便控制
主線程會(huì)卡访雪,F(xiàn)eed卡頓详瑞,馬上使用的話會(huì)發(fā)現(xiàn)掂林。
不夠優(yōu)雅,可維護(hù)性差
更優(yōu)方案 延遲方案
核心思想坝橡,對(duì)延遲任務(wù)進(jìn)行分批初始化
利用IdleHandler特性泻帮,空閑執(zhí)行
8啟動(dòng)優(yōu)化其他方案
優(yōu)化總方針
異步、延遲驳庭、懶加載
技術(shù)刑顺、業(yè)務(wù)相結(jié)合
注意事項(xiàng)
wall time與Cpu time
監(jiān)控的完善
收斂啟動(dòng)修改代碼權(quán)限
其他方案
提前加載SharedPreferences:
1Multidex之前加載,利用此階段的CPU饲常。
2復(fù)寫getApplicationContext()返回this
啟動(dòng)階段不啟動(dòng)子進(jìn)程
子進(jìn)程會(huì)共享CPU資源,導(dǎo)致主進(jìn)程CPU緊張
注意啟動(dòng)順序:APP onCreate 之前是ContentProvider
類加載優(yōu)化:提前異步類加載
Class.forName()之家在類本身及其靜態(tài)變量的應(yīng)用類
new 類 可以額外加載類成員變量的引用類
其他
啟動(dòng)階段抑制GC
CPU鎖頻(提一句狼讨,可能導(dǎo)致耗電量增加)