有关于Android第一次启动出现的黑屏和白屏的过渡问题,看了很多相关的资料和文章,决定将自己的一些见解和处理方式总结一下,以便日后在遇到有个思路,先大致列为几个部分。
一:应用点击启动的过程描述和冷热启动的概念
手机本身的桌面也是一个应用,所有的应用图标在桌面上的点击事件就像是应用中的控件OnCLick点击事件一样,都是处于用户点击的时候监听的状态,一个应用在桌面上被用户点击之后到启动是一个复杂的过程,对这个过程描述比较详细的文章:https://blog.csdn.net/qian520ao/article/details/78156214可供参考。大致过程就是
1、Launcher通知AMS启动APP的MainActivity,也就是清单文件设置启动的Activity。
2、AMS记录要启动的Activity信息,并且通知Launcher进入pause状态。
3、Launcher进入pause状态后,通知AMS已经paused了,可以启动了。
4、app未开启过,所以AMS启动新的进程,并且在新进程中创建ActivityThread对象,执行其中的main函数方法。
5、app主线程启动完毕后通知AMS,并传入applicationThread以便通讯。
6、AMS通知绑定Application并启动MainActivity。
7、启动MainActivitiy,并且创建和关联Context,最后调用onCreate方法。
在这里要插入一个概念,在启动整个应用的过程中,就会因不同情况出现冷启动和热启动两种,冷启动就是在启动该应用前,系统中没有该应用的任何进程信息。 (第一次打开应用、杀死了进程再打开、时间最长)热启动则是用户使用返回键推出应用,然后马上又重新启动应用。二者的区别是冷启动没有创建过初始化,热启动是已经初始化再打开。
二:为什么会首次加载出现白屏或者黑屏的效果
说完启动过程,就要来说明一下为什么会出现白屏或者黑屏的问题。在应用冷启动和热启动的过程中,总归是要创建这个应用进程的,所以在这个过程中Google为了增加用户的体验,就做了一个过渡效果的Windows窗口,这个Windows窗口效果根据你设定的启动页面的主题来显示,如果你设置的主题是Light则过渡窗口是默认白屏,反之则是默认黑屏,当应用第一次加载打开或者进程被杀死重新启动的时候(冷启动),那么这个过渡窗口就会显示较长时间,热启动则会一闪而过,总之黑屏和白屏的产生,就是这样来的
三:如何去优化这个过程
优化的方法网上有很多,经过每个方法的尝试和实践测试,有一个自己的方式来实现,另外结尾会归纳一下其他几种方式不采纳的原因
我的方式是通过设置
Style.Xml主题
<!-- 启动页主题 -->
<style name="StartAppTheme" parent="@android:style/Theme.NoTitleBar.Fullscreen">
<item name="android:windowBackground">@drawable/xxxxx</item>
<item name="android:windowIsTranslucent">false</item>
</style>
设置清单文件AndroidManifest.Xml
<activity
android:name=".activity.xxxxxActivity"
android:label="@string/xxxxx"
android:screenOrientation="portrait"
android:theme="@style/StartAppTheme">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
引用xxxxx的drawable文件
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:bottom="xxxdp">
<color android:color="#ffffff" />
</item>
<item>
<color android:color="#ffffff" />
</item>
<item android:bottom="xxxdp">
<bitmap
android:gravity="bottom|center_horizontal"
android:src="@drawable/你的logo图片" />
</item>
<item android:bottom="xxxdp">
<bitmap
android:gravity="bottom|center_horizontal"
android:src="@drawable/你的logo图片" />
</item>
</layer-list>
这里之所以用自定义的drawable,是因为我们没有现成的启动图片,而且为了和随后启动的广告页面保持一致,所以采用了一个白背景加Logo底的自定义效果,这样当广告页加载的时候可以平稳无差别过渡。关于Android中layer-list使用,也可以搜到大部分文章,这里只简单讲一下layer-list是将多个drawable按照顺序层叠在一起显示,默认情况下,所有的item中的drawable都会自动根据它附上view的大小而进行缩放,
layer-list中的item是按照顺序从下往上叠加的,即先定义的item在下面,后面的依次往上面叠放。所以有了如上的自定义Drawable效果
附:
使用方案
<item name="android:windowIsTranslucent">true</item>将过渡窗口设置成无,即透明效果,这种方式如果遇到手机硬件配置好的情况,可能会平稳启动应用,并且无黑屏闪显,但是如果遇到配置很差的手机,会出现用户点击后卡在原地很久才打开应用的错觉,其实只是过渡效果透明了,所以为了不影响用户体验,还是建议不使用
使用方案
<style name="StartAppTheme" parent="@android:style/Theme.NoTitleBar.Fullscreen">
<item name="android:windowBackground">@drawable/图片</item>
<item name="android:windowIsTranslucent">false</item>
</style>
虽然可以用一张图片替换过渡效果,并且效果不错,但是如果启动页和该图片有大的出入,会给用户一种视差,不能起到平稳过度的感觉
使用方案
getActivity().getWindow().getDecorView().setBackground(new BitmapDrawable(blurBitmap));
动态去替换过渡页,没有尝试过,不过感觉过渡界面本身没那么复杂多变,而且将动态设置放在执行类中,也担心可能无效,所以并没做过多尝试