目录
前言
在日常Android项目开发工作中,我们经常会遇到一种小情况,就是点击应用桌面图标后会出现片刻的黑屏效果。虽然这种情况并不是一个bug,也不是人为造成的结果,但这样总归会觉得是我们的应用启动缓慢和运行卡顿。当用户觉得这款应用不流畅,即降低用户体验,造成用户流失就是公司的损失了。因此,本章就来搞清楚这种情况是怎么回事,如何解决这一问题。
一、案件重演
一般应用开发中都会创建启动页、欢迎页或广告页,SplashActivity.class 实现代码大致如下:
AndroidManifest.xml
<activity
android:name=".SplashActivity"
android:screenOrientation="portrait"
android:theme="@style/ThemeSplash"> //自定义主题
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
styles.xml (注意细节!)
<style name="ThemeSplash" parent="Theme.AppCompat.Light.NoActionBar">
//注意!!window背景设为白色!!!
<item name="android:windowBackground">@android:color/white</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowFullscreen">true</item>
<item name="windowActionBar">false</item>
//没有状态栏,即全屏
<item name="windowNoTitle">true</item>
</style>
activity_splash.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@mipmap/bg_splash"
tools:context="com.example.makeapp.SplashActivity">
</RelativeLayout>
SplashActivity.class
public class SplashActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_splash);
}
}
这样运行起来,会出现白屏现象。
二、原因分析
如果不懂视图加载原理的同学,建议移步学习Android setContentView()\LayoutInflater\View 源码原理分析
从上面在SplashActivity.class中可见:onCreate生命周期中执行了setContentView(R.layout.activity_splash)。我们进入setContentView源码中看一下。
public void setContentView(@LayoutRes int layoutResID) {
getWindow().setContentView(layoutResID);
initWindowDecorActionBar();
}
这里注意调用的是 getWindow().setContentView(layoutResID) 。这说明先调用了Window的setContentView方法。(Window是一个抽象对象,它的具体实现类就是PhoneWindow)
我们再看一下PhoneWindow中的setContentView() 的源码:
@Override
public void setContentView(int layoutResID) {
if (mContentParent == null) {
installDecor();
} else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
mContentParent.removeAllViews();
}
if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID,
getContext());
transitionTo(newScene);
} else {
//解析布局
mLayoutInflater.inflate(layoutResID, mContentParent);
}
mContentParent.requestApplyInsets();
final Callback cb = getCallback();
if (cb != null && !isDestroyed()) {
cb.onContentChanged();
}
}
注意其中调用了 mLayoutInflater.inflate(layoutResID, mContentParent); 说明是将SplashActivity的R.layout.activity_splash布局加载到了其宿主PhoneWindow中了。
所以,在页面启动时,系统会先绘制窗体布局,这时候SplashActivity布局资源还没加载完成,于是就先显示了window的默认背景色。
三、解决方案
1、我们将把启动图 bg_splash.png 设置为窗体背景色;
2、在窗体背景色显示时,后台请求广告图或加载应用中的广告资源;
3、广告图请求成功或失败就显示SplashActivity自己真实的样子。
<style name="ThemeSplash" parent="Theme.AppCompat.Light.NoActionBar">
//设置启动图为窗体背景色
<item name="android:background">@mipmap/bg_splash</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowFullscreen">true</item>
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
</style>
至此,应该可以就不会出现黑白屏了。
参考链接https://blog.csdn.net/zivensonice/article/details/51691136