App 啟動(dòng)時(shí)
一般app分為冷啟動(dòng)和熱啟動(dòng)
- 冷啟動(dòng): app點(diǎn)擊啟動(dòng)前,它的進(jìn)程不在系統(tǒng)里,需要系統(tǒng)新創(chuàng)建一個(gè)進(jìn)程分配給它啟動(dòng)
- 熱啟動(dòng),app在冷啟動(dòng)后用戶將app退到后臺(tái),app的進(jìn)程還在系統(tǒng)中的情況下,用戶重新啟動(dòng)進(jìn)入app的過程,當(dāng)然這個(gè)過程做的事情非常少
因此一般app啟動(dòng)速度都是指冷啟動(dòng)的優(yōu)化
用戶能感知到啟動(dòng)慢,其實(shí)都是發(fā)生在主線程上。而主線程慢的原因有很多,比如在主線程上執(zhí)行大文件讀寫操作,在渲染周期中執(zhí)行大量計(jì)算等。
app啟動(dòng)時(shí)的過程(用戶點(diǎn)擊app開始,到用戶看到第一個(gè)界面之間的時(shí)間):
- main()函數(shù)執(zhí)行之前;
- main()函數(shù)執(zhí)行之后;
- 首屏渲染完成后。
main()函數(shù)執(zhí)行之前
在main()函數(shù)執(zhí)行前,系統(tǒng)主要會(huì)做以下幾件事:
- 加載可執(zhí)行文件(app的.o文件的集合)
- 加載動(dòng)態(tài)鏈接庫,進(jìn)行rebase指針調(diào)整和bind符號(hào)綁定
- Objc 運(yùn)行時(shí)的初始處理,包括Objc相關(guān)類的注冊(cè),category注冊(cè),selector唯一性檢查
- 初始化,包括了執(zhí)行 +load()方法,attribute((constructor)) 修飾的函數(shù)的調(diào)用,創(chuàng)建c++靜態(tài)全局變量
因此在這個(gè)階段,對(duì)于優(yōu)化啟動(dòng)速度如下: - 減少動(dòng)態(tài)庫加載
- 加少加載啟動(dòng)后不會(huì)去使用的類或方法
- +load() 方法里的內(nèi)容可以放到首屏渲染完成后在執(zhí)行,或使用 +initialize() 方法替換掉。
- 控制 C++ 全局變量的數(shù)量
main() 函數(shù)執(zhí)行后:
main() 函數(shù)執(zhí)行后的階段,是指從main() 函數(shù)執(zhí)行開始,到AppDelegate 的 didFinishLaunchingWithOptions 方法里首屏渲染相關(guān)方法執(zhí)行完成。
首頁的業(yè)務(wù)代碼都是要在這個(gè)階段(渲染前執(zhí)行) - 首屏初始化所需配置文件的讀寫操作
- 首屏列表大數(shù)據(jù)的讀取
- 首批渲染的大量計(jì)算
因此梳理出哪些時(shí)首屏渲染必要的初始化功能,哪些是app啟動(dòng)必要的初始化功能,哪些是只需要在對(duì)應(yīng)功能開始使用時(shí)才需要初始化的
首屏渲染完成后
首屏渲染后的階段,主要完成的是,非首屏其他業(yè)務(wù)服務(wù)模塊的初始化,監(jiān)聽的注冊(cè),配置文件的讀取等,也就是 didFinishLaunchingWithOptions 作用域內(nèi)執(zhí)行首屏渲染之后所有方法執(zhí)行完成
這個(gè)階段用戶已經(jīng)能夠看到app的首頁信息
總結(jié)
- main() 函數(shù)開始執(zhí)行后渲染完成前只處理首屏相關(guān)的業(yè)務(wù),其他無關(guān)的業(yè)務(wù)放在首屏渲染完成后去做
- 在首屏渲染完成前主線程中一個(gè)耗時(shí)的操作滯后或者通過異步執(zhí)行