注意是冷启动的时候,点击 App icon 立刻就会显示一个默认(或者提前设置好的)背景,这个背景就是 android:windowbackground
,我们可以在 theme.xml
中设置为我们的冷启动背景,从肉眼观感的角度去优化 App 启动的问题,那么回到我的疑问:
- 冷启动的时候
windowbackground
是什么时候设置的呢?
为了找到这个问题,跟了几遍 ActivityThread 里面 Activity 启动流程的代码也没找到具体的实现,后来无意和群友聊天的过程中群友找到一个关键类:
SplashScreen.java
我顺着这个逻辑跟着源码一直定位到 ActivityManagerService.resumeTopActivityInnerLocked()
,
ActivityStack.addStartingWindowsForVisibleActivities(taskSwitch)
,这个调用会一直到 PhoneWindowManager.addSplashScreen()
-> addSplashscreenContent()
方法
private void addSplashscreenContent(PhoneWindow win, Context ctx) {
final TypedArray a = ctx.obtainStyledAttributes(R.styleable.Window);
final int resId = a.getResourceId(R.styleable.Window_windowSplashscreenContent, 0);
a.recycle();
if (resId == 0) {
return;
}
final Drawable drawable = ctx.getDrawable(resId);
if (drawable == null) {
return;
}
// We wrap this into a view so the system insets get applied to the drawable.
final View v = new View(ctx);
v.setBackground(drawable);
win.setContentView(v);
}
简列一些重点:
- 搜
Window_windowBackground
属性,FW里只有PhoneWindowManager#addSplashScreen()
和PhoneWindow
里出现过。 addSplashScreen()
里读取该属性决定是否要复写context
,PhoneWindow
则是读取它用作背景。- 由
addSplashScreen()
查调用栈,最后会指向ActivityRecord#showStartingWindow()
。 showStartingWindow()
调用的地方较多,我觉得ActivityStack#resumeTopActivityInnerLocked()
的调用最符合描述的场景。- 无论是 launcher 还是 App 启动都是通过 AMS 的 startActivity 分发而来,在目标 App 启动前都要经过
resumeTopActivityInnerLocked()
。这时候会调用addSplashScreen
创建一个属于目标进程但不属于目标activity 的独立 window,为了启动快或显示欢迎广告啥的。没有加log验证,只是猜测。