APP闪屏页的正确打开方式
breewf

闪屏页(Splash),顾名思义,就是一闪而过的页面,当然,它大多时候可能并不是一闪而过,而是要我们等待数秒,因为我们的app在打开、初始化、加载的过程中都需要一定的时间,尤其是首次启动(冷启动)或者手机性能较差的时候耗时更加明显,这时候我们什么也看不到。与其毫无意义的等待(黑屏or白屏),何不展示一些有趣或者有意思的东西呢?所以闪屏页一般被用来展示公司Logo、标语或者App的特性等,当然,展示广告的就比较坑啦。那么问题来啦,既然我都设置了闪屏页,为什么我的app启动的时候还是会黑屏或白屏呢?

问题由来:Starting Window

当打开一个Activity时,如果这个Activity所属的应用还没有在运行,系统会为这个Activity所属的应用创建一个进程,但进程的创建与初始化都需要时间,在这个动作完成之前,如果初始化的时间过长,屏幕上可能没有任何动静,用户会以为没有点到相应的按钮。所以既不能停在原来的地方但又无法显示应用程序,怎么办呢?这就有了Starting Window(也称之为Preview Window)。

Starting Window就是一个用于在应用程序进程创建并初始化成功前显示的临时窗口,拥有的Window Type是TYPE_APPLICATION_STARTING。在程序初始化完成前显示这个窗口,以告知用户系统已经知道了他要打开这个应用并做出了响应,当程序初始化完成后显示用户UI并移除这个窗口。

一般我们会对Application和Activity设置不同的Theme,系统就是根据这个Theme初始化Starting Window的。Window布局的顶层是DecorView,Starting Window就是显示一个空的但是应用了Activity指定的Theme(如果Activity没有指定就用Application的)的DecorView。在Theme中可以指定很多东西,如窗口的背景,是否全屏,是否透明等,通过给Activity指定Theme,系统就可以在我们的应用初始化完成之前将这个Theme应用到Starting Window,这样看起来就像我们的应用已经启动起来了,只是数据内容还没有初始化好。

这个Starting Window我们都见过,不过可能没留意过,其实就是开启程序时黑屏(或白屏)的那个窗口,也就是我们上面提到的问题的来源。

解决办法

既然启动的时候是黑屏或者白屏,那么把Activity的窗口设置成透明背景是不是就可以了呢?如下:

1
2
3
4
<style name="SplashTheme" parent="AppTheme">
<item name="android:windowFullscreen">true</item>
<item name="android:windowIsTranslucent">true</item>
</style>

如上设置闪屏页主题背景透明启动APP时,我们的StartingWindow会应用我们这个透明背景的主题,跳转时确实没有白屏和黑屏了,但是这样设置会产生下面的问题:用户点击我们APP图标后,需要等待几秒左右的时间才会显示我们的app界面。造成了APP启动速度慢的假象,其实Activity已经启动了,只是background是透明的,这时候你点击桌面的其他地方是无效的。

秒开方案

既然可以让Window白屏黑屏或者透明,那么是不是可以设置其他颜色或者图片来实现APP的秒开呢?答案是肯定的。

我们之前设置了Window透明,实现了去掉白屏和黑屏,现在要弄一个颜色或者图片来代替白屏和黑屏,所以首先要把原来style中的透明属性去掉。然后给Window设置一个背景颜色或者图片。

1.首先在res/drawable下新建一个layer-list,比如splash.xml:

1
2
3
4
5
6
7
8
9
10
11
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 背景颜色 -->
<item android:drawable="@color/white" />

<item>
<!-- 图片 -->
<bitmap
android:src="@mipmap/splash" />
</item>
</layer-list>

2、给闪屏页设置主题背景:

1
2
3
4
5
6
<style name="SplashTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- 闪屏页背景引用刚才写好的 -->
<item name="android:windowBackground">@drawable/splash</item>
<item name="android:windowFullscreen">true</item>
<!-- <item name="android:windowIsTranslucent">true</item> --> <!-- 透明背景不要了 -->
</style>

3、在AndroidManifest.xml中定义SplashActivity的theme为SplashTheme:

1
2
3
4
5
6
7
8
9
<activity
android:name=".SplashActivity"
android:theme="@style/SplashTheme">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

4.SplashActivity的实现,在onCreate()启动你的MainActivity即可:

1
2
3
4
5
6
7
8
9
10
public class SplashActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// setContentView(R.layout.activity_splash);
startActivity(new Intent(SplashActivity.this, MainActivity.class));
finish();
}
}

特别注意:为了保证启动速度,SplashActivity不要调用setContentView()方法。

好了,这就是正确的闪屏页打开方式,跟启动黑屏、白屏说拜拜吧。

参考链接:
带你重新认识:Android Splash页秒开 Activity白屏 Activity黑屏
Splash Screens the Right Way