当我们打开一个应用程序时,会出现一个启动界面,不同的手机,启动界面不一样,甚至有的手机还会出现一段时间的黑屏,出现时间的长短与启动启动的速度有关。
启动画面是什么?
应用程序启动时,我们看到了启动的画面,它上面显示的是看到的内容,内容是在哪儿配置的呐?它究竟是什么呐?
配置内容
我们在应用程序配置清单AndroidManifest.xml中的application,activity节点配置的android:theme属性,就是应用启动时显示配置信息,如果不配置theme则获取系统默认属性,在该属性下面我们可以看到有以下节点配置:
<style name="Theme">
<!-- Window attributes -->
<item name="windowBackground">@drawable/screen_background_selector_dark</item>
</style>
可以看到在主题的Theme中可以配置关于窗口的属性,其中windowBackground节点,当应用启动时显示就该节点配置的信息。
怎么复写?
系统默认的启动界面一般都是白色或者黑色的画面,因此如果你的产品色是白色,而启动界面却是黑色,则会在启动过程中有一个从黑变白的过程,如果应用启动非常快,则会一闪而过,导致体验太差。从上面可以知道应用启动读取的是windowBackground节点,那我们直接复写该节点就可以了。
> 样例
<style name="WelcomeTheme" parent="@android:style/Theme.Light.NoTitleBar.Fullscreen">
<item name="colorPrimary">@color/white</item>
<item name="colorPrimaryDark">@color/color_ffcccccc</item>
<item name="android:windowFullscreen">true</item>
<item name="android:windowBackground">@drawable/splash_bg</item>
</style>
我们可以自定义一个主题,复写掉windowBackground节点,这样在应用启动时就会显示你配置的界面,该界面你可以显示你应用的logo等信息来增强品牌,最主要的是提升应用体验,不过也有更多厂商将这个当做了一个收入的来源,都挂了启动广告。。。。。。
显示过程
从上面我们已经知道如果更改启动画面为自己的画面,如果只需要学会怎么复写,则到这一步就OK了; 可是作为搬砖的,我们不仅要知其然更要知其所以然。因此我们从代码的角度来看看他的显示过程。
我们点击home界面的应用图标,可以看到是在home应用程序里面其实调用了startActivity(intent);intent中对应的是包名与类名,这里的类就是我们的主activity,主acitivity主要用下面的信息来进行区分:
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
Home应用程序中是怎么获取到该类名的?我们在前一篇Android应用程序包解析过程浅析中有关于AndroidManifest的解析过程,解析的内容经过ActivityManagerService读取action为MAIN,category为LAUNCHER的activity显示到界面上。
因此我们跟进到startActivity中去看看:
@Override
public void startActivity(Intent intent) {
this.startActivity(intent, null);
}
@Override
public void startActivity(Intent intent, @Nullable Bundle options) {
if (options != null) {
startActivityForResult(intent, -1, options);
} else {
// Note we want to go through this call for compatibility with
// applications that may have overridden the method.
startActivityForResult(intent, -1);
}
}
public void startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options) {
if (mParent == null) {
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, this,
intent, requestCode, options);
if (ar != null) {
mMainThread.sendActivityResult(
mToken, mEmbeddedID, requestCode, ar.getResultCode(),
ar.getResultData());
}
if (requestCode >= 0) {
// If this start is requesting a result, we can avoid making
// the activity visible until the result is received. Setting
// this code during onCreate(Bundle savedInstanceState) or onResume() will keep the
// activity hidden during this time, to avoid flickering.
// This can only be done when a result is requested because
// that guarantees we will get information back when the
// activity is finished, no matter what happens to it.
mStartedActivity = true;
}
cancelInputsAndStartExitTransition(options);
// TODO Consider clearing/flushing other event sources and events for child windows.
} else {
if (options != null) {
mParent.startActivityFromChild(