首先介紹下什么是啟動(dòng)窗口,對(duì)于大部分應(yīng)用冷啟動(dòng)時(shí)的場(chǎng)景都會(huì)有啟動(dòng)窗口倍谜,為了讓效果更明顯迈螟,在如下代碼中(只是一個(gè)基本的可以運(yùn)行的應(yīng)用即可)添加了sleep5s的代碼,在按recent鍵移除應(yīng)用后枢劝,再點(diǎn)擊桌面圖標(biāo)井联,即可看到啟動(dòng)窗口效果,即使點(diǎn)擊后界面內(nèi)容顯示出來(lái)前的白色界面
啟動(dòng)窗口有什么用途呢您旁,從邏輯及效果看烙常,其應(yīng)該主要是用于一個(gè)過(guò)渡,比如上述添加了5s延時(shí)的場(chǎng)景中鹤盒,如果沒(méi)有啟動(dòng)窗口蚕脏,那么點(diǎn)擊了桌面的應(yīng)用圖標(biāo)后,會(huì)有5s多的時(shí)間用戶看不到什么反應(yīng)侦锯,會(huì)讓用戶覺得是不是應(yīng)用沒(méi)啟動(dòng)啊驼鞭,我們可以試驗(yàn)下,可在style中添加
<item name="android:windowDisablePreview">true</item>
項(xiàng)尺碰,即可禁用啟動(dòng)窗口挣棕,如
對(duì)用戶和應(yīng)用來(lái)說(shuō)一個(gè)白色界面作為啟動(dòng)窗口可能不是很美觀,也可以做一些自定義行為
1亲桥、一般需要較長(zhǎng)時(shí)間加載的應(yīng)用啟動(dòng)窗口的作用更明顯洛心,所以可以實(shí)現(xiàn)個(gè)簡(jiǎn)單的Activity作為歡迎界面,待準(zhǔn)備工作加載完成后题篷,即可跳轉(zhuǎn)到正式界面
2词身、啟動(dòng)窗口界面內(nèi)容本身有配置的方法,可通過(guò)配置
<item name="android:windowSplashscreenContent"> </item>
項(xiàng)來(lái)設(shè)置啟動(dòng)窗口的內(nèi)容界面番枚,顯然這里可設(shè)置一個(gè)drawable法严,在添加啟動(dòng)窗口界面時(shí)损敷,會(huì)將該drawable添加到啟動(dòng)窗口的內(nèi)容視圖中,如
另外可通過(guò)設(shè)置<item name="windowAnimationStyle"> </item>來(lái)設(shè)置相關(guān)動(dòng)畫深啤,這里就不舉例了
添加啟動(dòng)窗口代碼邏輯(使用android-10.0.0_r39分支代碼查看)
(添加時(shí)機(jī)拗馒,一般是前臺(tái)task切換時(shí)可能會(huì)觸發(fā),比較特別地是一般新啟動(dòng)一個(gè)應(yīng)用墓塌,或殺掉一個(gè)應(yīng)用進(jìn)程后啟動(dòng)該應(yīng)用時(shí)瘟忱,這種情況下一般都會(huì)有啟動(dòng)窗口,如設(shè)置苫幢、電話等應(yīng)用新啟動(dòng)時(shí)访诱,會(huì)先顯示一個(gè)空白的界面,然后顯示設(shè)置界面內(nèi)容韩肝,那個(gè)空白的界面即其啟動(dòng)窗口)
ActivityRecord.java-showStartingWindow
在這里會(huì)調(diào)用其addStartingWindow方法(ActivityRecord)
顯然触菜,這里主要是調(diào)用了AppWindowToken的addStartingWindow方法,查看AppWindowToken的addStartingWindow方法哀峻,這里邏輯稍多涡相,介紹下其主要部分
1、該方法中會(huì)調(diào)用getStartingWindowType方法根據(jù)場(chǎng)景獲取需要啟動(dòng)窗口類型
其中AppWindowToken的getStartingWindowType方法邏輯如下
從上述代碼可知getStartingWindowType方法可能返回三種值 STARTING_WINDOW_TYPE_NONE剩蟀,STARTING_WINDOW_TYPE_SPLASH_SCREEN 催蝗,STARTING_WINDOW_TYPE_SNAPSHOT
返回類型為STARTING_WINDOW_TYPE_NONE時(shí)看其邏輯應(yīng)該是無(wú)啟動(dòng)窗口的
返回類型為STARTING_WINDOW_TYPE_SPLASH_SCREEN時(shí)即可能會(huì)有場(chǎng)景中的啟動(dòng)窗口,比如在殺掉設(shè)置進(jìn)程后(點(diǎn)擊recent導(dǎo)航鍵育特,移除設(shè)置)丙号,點(diǎn)擊設(shè)置圖標(biāo)后馬上dumpsys window信息可看到有如下窗口,這就是啟動(dòng)窗口的窗口缰冤,也是這里主要介紹的邏輯(如下是設(shè)置的啟動(dòng)窗口)
返回類型為STARTING_WINDOW_TYPE_SNAPSHOT時(shí)犬缨,會(huì)調(diào)用createSnapshot方法,這里也會(huì)臨時(shí)添加一個(gè)特殊的窗口棉浸,比如進(jìn)入設(shè)置后怀薛,回到桌面,點(diǎn)擊recent導(dǎo)航鍵迷郑,然后點(diǎn)擊枝恋,這里就不細(xì)將了
2、如果theme中設(shè)置了windowIsTranslucent為true嗡害,或者設(shè)置了windowIsFloating為true鼓择,或者設(shè)置了windowDisablePreview為true,則不會(huì)添加啟動(dòng)窗口
3就漾、AppWindowToken的addStartingWindow方法的主要邏輯會(huì)創(chuàng)建一個(gè)SplashScreenStartingData對(duì)象,然后調(diào)用scheduleAddStartingWindow方法
AppWindowToken的addStartingWindow方法就到這里了念搬,繼續(xù)跟蹤其主要邏輯
scheduleAddStartingWindow方法主要是將一個(gè)mAddStartingWindow任務(wù)放到一個(gè)handler隊(duì)首去執(zhí)行
再看下mAddStartingWindow的邏輯:
這里mStartingData即是前面addStartingWindow中創(chuàng)建的SplashScreenStartingData對(duì)象(只針對(duì)這里STARTING_WINDOW_TYPE_SPLASH_SCREEN的情況)抑堡,這里主要邏輯即調(diào)用SplashScreenStartingData的createStartingSurface方法
顯然摆出,SplashScreenStartingData的createStartingSurface方法中調(diào)用了PhoneWindowManager的addSplashScreen方法而PhoneWindowManager的addSplashScreen方法也即是添加啟動(dòng)窗口的地方
如上即是PhoneWindowManager的addSplashScreen方法的代碼,其主要部分就是創(chuàng)建一個(gè)PhoneWindow對(duì)象首妖,然后設(shè)置些屬性和視圖(基本上應(yīng)該是全屏偎漫,內(nèi)容應(yīng)該是根據(jù)theme相關(guān)只有框架的界面,具體內(nèi)容一般為空白有缆,有的有圖標(biāo)和標(biāo)題)象踊,然后調(diào)用WindowManager服務(wù)的addView方法添加窗口
這里也有幾個(gè)可設(shè)置相關(guān)屬性的地方
1、windowAnimationStyle
應(yīng)該可以通過(guò)設(shè)置windowAnimationStyle設(shè)置相關(guān)動(dòng)畫
2棚壁、windowSplashscreenContent
根據(jù)啟動(dòng)窗口調(diào)用的addSplashscreenContent方法杯矩,應(yīng)該可以通過(guò)設(shè)置windowSplashscreenContent屬性來(lái)設(shè)置啟動(dòng)窗口的內(nèi)容圖片
在添加啟動(dòng)窗口呼,待合適的時(shí)機(jī)袖外,如應(yīng)用界面繪制完成則會(huì)觸發(fā)AppWindowToken的removeStartingWindow方法調(diào)用史隆,然后移除啟動(dòng)窗口,這里就不細(xì)述了