前言
app首幀的定義主要有兩種解釋。
- app啟動(dòng)可見(jiàn)時(shí)的第一幀,一般是logo展示頁(yè)盆均,沒(méi)有做logo展示頁(yè)則是白屏頁(yè);
- 人為定義的app的第一個(gè)頁(yè)面的第一幀漱逸;
這里第一種解釋沒(méi)有太大的意義泪姨,因?yàn)榇藭r(shí)一般都被Application的初始化給阻塞著,所以咱們主要討論第二種解釋饰抒。
作用
為啥要定義一個(gè)首幀呢肮砾?
保證頁(yè)面對(duì)用戶(hù)可見(jiàn)可交互的同時(shí),處理一些可以延遲初始化的邏輯袋坑,減輕Application的初始化工作量仗处,提升app啟動(dòng)速度,同時(shí)可懶加載一些業(yè)務(wù)咒彤,優(yōu)化用戶(hù)體驗(yàn)疆柔。
定義
通常一個(gè)app的第一個(gè)可交互的頁(yè)面,是首頁(yè)镶柱,我們就拿MainActivity來(lái)講吧旷档。
什么是MainActivity的第一幀?
我們使用viewTreeObserver.addOnGlobalLayoutListener
監(jiān)聽(tīng)頁(yè)面layout完成歇拆,但是layout完成不代表繪制完成鞋屈。我們可以看ViewRootImpl的源碼:
//performTraversals()方法的簡(jiǎn)化版
void performTraversals() {
//......
performMeasure();
//......
performLayout();
//......
performDraw();
}
我們可以知道layout完成之后馬上就會(huì)draw,所以使用在onGlobalLayout
中使用Handler post一次即可保證第一幀頁(yè)面可見(jiàn)故觅。
完整示例:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val viewTreeObserver = window.decorView.viewTreeObserver
viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
override fun onGlobalLayout() {
Handler(Looper.getMainLooper()).post {
println("首幀")
viewTreeObserver.removeOnGlobalLayoutListener(this)
}
}
})
}
總結(jié)
首幀之后到底可以做那些事兒厂庇?
- 網(wǎng)絡(luò)異步IO,將app啟動(dòng)時(shí)非必要及時(shí)加載的網(wǎng)絡(luò)請(qǐng)求放在首幀以后输吏。
一般app啟動(dòng)過(guò)程中有許多埋點(diǎn)权旷,我們可以把這些埋點(diǎn)延后上報(bào),減少app啟動(dòng)時(shí)的線(xiàn)程消耗贯溅。
在減少網(wǎng)絡(luò)請(qǐng)求的時(shí)候拄氯,還可以減少本地IO躲查,減輕磁盤(pán)IO負(fù)載。 - 布局異步初始化译柏,刪掉接下來(lái)的頁(yè)面xml解析時(shí)間镣煮;
- 非啟動(dòng)必須庫(kù)的異步加載,需要注意的時(shí)鄙麦,這種庫(kù)使用一定要做兜底操作典唇;
- 一些業(yè)務(wù)的懶加載;