Java Android - 防止启动时出现白屏
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/37437037/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Android - Prevent white screen at startup
提问by Y.S
As we all know, many Android apps display a white screen very briefly before their first Activity
comes into focus. This problem is observed in the following cases:
众所周知,许多 Android 应用程序在首次Activity
成为焦点之前会非常短暂地显示白屏。在以下情况下会观察到此问题:
Android apps that extend the global
Application
class and perform major initializations therein. TheApplication
object is always created before the firstActivity
(a fact that can be observed in the debugger), so this makes sense. This is the cause of the delay in my case.Android apps that display the default preview window before the splash screen.
扩展全局
Application
类并在其中执行主要初始化的Android 应用程序。的Application
对象总是之前首先创建的Activity
(即可以在调试器中观察到的事实),所以这是有意义的。这就是我的情况延迟的原因。在启动画面之前显示默认预览窗口的 Android 应用程序。
Setting android:windowDisablePreview = "true"
obviously does not work here. Nor can I set the parent theme of the splash screen to Theme.Holo.NoActionBar
as described here, because [unfortunately] my splash screen makes use of an ActionBar
.
设置android:windowDisablePreview = "true"
显然在这里不起作用。我也不能启动画面的父主题设置为Theme.Holo.NoActionBar
所描述的在这里,因为[不幸]我闪屏利用的ActionBar
。
Meanwhile, apps that do not extend the Application
class do notshow the white screen at startup.
同时,不扩展Application
类的应用程序在启动时不会显示白屏。
The thing is, ideally the initializations performed in the Application
object need to occur beforethe first Activity
is shown. So my question is, how can I perform these initializations on app startup withoutusing an Application
object? Possibly using a Thread
or Service
, I suppose?
问题是,理想情况下,Application
对象中执行的初始化需要在第一个Activity
显示之前发生。所以我的问题是,如何在不使用Application
对象的情况下在应用程序启动时执行这些初始化?可能使用 aThread
或Service
,我想?
This is an interesting problem to think about. I can't bypass it the usual way (by setting the NoActionBar
theme), as tragically my Splash screen actually has an ActionBar
due to some unrelated reasons.
这是一个值得思考的有趣问题。我不能以通常的方式绕过它(通过设置NoActionBar
主题),因为不幸的是,ActionBar
由于一些不相关的原因,我的启动画面实际上有一个。
Note:
笔记:
I have already referred to the following questions:
我已经提到了以下问题:
References:
参考:
采纳答案by Ivan Milisavljevic
The problem with white background is caused because of android's cold start while the app loads to memory, and it can be avoided with this:
白色背景的问题是由于android在应用程序加载到内存时冷启动引起的,可以通过以下方式避免:
public class OnboardingWithCenterAnimationActivity extends AppCompatActivity {
public static final int STARTUP_DELAY = 300;
public static final int ANIM_ITEM_DURATION = 1000;
public static final int ITEM_DELAY = 300;
private boolean animationStarted = false;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
setTheme(R.style.AppTheme);
getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_onboarding_center);
}
@Override
public void onWindowFocusChanged(boolean hasFocus) {
if (!hasFocus || animationStarted) {
return;
}
animate();
super.onWindowFocusChanged(hasFocus);
}
private void animate() {
ImageView logoImageView = (ImageView) findViewById(R.id.img_logo);
ViewGroup container = (ViewGroup) findViewById(R.id.container);
ViewCompat.animate(logoImageView)
.translationY(-250)
.setStartDelay(STARTUP_DELAY)
.setDuration(ANIM_ITEM_DURATION).setInterpolator(
new DecelerateInterpolator(1.2f)).start();
for (int i = 0; i < container.getChildCount(); i++) {
View v = container.getChildAt(i);
ViewPropertyAnimatorCompat viewAnimator;
if (!(v instanceof Button)) {
viewAnimator = ViewCompat.animate(v)
.translationY(50).alpha(1)
.setStartDelay((ITEM_DELAY * i) + 500)
.setDuration(1000);
} else {
viewAnimator = ViewCompat.animate(v)
.scaleY(1).scaleX(1)
.setStartDelay((ITEM_DELAY * i) + 500)
.setDuration(500);
}
viewAnimator.setInterpolator(new DecelerateInterpolator()).start();
}
}
}
layout
布局
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
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="?colorPrimary"
android:orientation="vertical"
>
<LinearLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:orientation="vertical"
android:paddingTop="144dp"
tools:ignore="HardcodedText"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="16dp"
android:alpha="0"
android:text="Hello world" android:textAppearance="@style/TextAppearance.AppCompat.Widget.ActionBar.Title.Inverse"
android:textColor="@android:color/white"
android:textSize="22sp"
tools:alpha="1"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="8dp"
android:alpha="0"
android:gravity="center"
android:text="This a nice text"
android:textAppearance="@style/TextAppearance.AppCompat.Widget.ActionBar.Subtitle.Inverse"
android:textSize="20sp"
tools:alpha="1"
/>
<Button
android:id="@+id/btn_choice1"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:layout_marginTop="48dp"
android:scaleX="0"
android:scaleY="0"
android:text="A nice choice"
android:theme="@style/Button"
/>
<Button
android:id="@+id/btn_choice2"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:scaleX="0"
android:scaleY="0"
android:text="Far better!"
android:theme="@style/Button"
/>
</LinearLayout>
<ImageView
android:id="@+id/img_logo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:src="@drawable/img_face"
tools:visibility="gone"
/>
</FrameLayout>
img face
头像
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"
android:opacity="opaque">
<item android:drawable="?colorPrimary"/>
<item>
<bitmap
android:gravity="center"
android:src="@drawable/img_face"/>
</item>
Add this theme to your splashscreen in the manifest
将此主题添加到清单中的启动画面
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="android:windowBackground">@null</item>
</style>
<style name="AppTheme.CenterAnimation">
<item name="android:windowBackground">@drawable/ll_face_logo</item>
</style>
which will produce efect like this
这将产生这样的效果
for more details and more solutions you can check this BlogPost
有关更多详细信息和更多解决方案,您可以查看此 博客帖子
回答by Shmuel
First of all, to remove the white screen read this - https://www.bignerdranch.com/blog/splash-screens-the-right-way/
首先,要删除白屏,请阅读此内容 - https://www.bignerdranch.com/blog/splash-screens-the-right-way/
But more importantly, optimize your initial load and defer any heavy work to when you have time to run it. Post your application class here if you want us to take a look at it.
但更重要的是,优化您的初始负载并将任何繁重的工作推迟到您有时间运行它。如果您希望我们查看它,请在此处发布您的应用程序课程。
回答by Sergey Shustikov
Did you try to put initialization to onActivityCreated
?
您是否尝试将初始化设置为onActivityCreated
?
Inside Application
class :
内部Application
类:
registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
if(activity.getClass().equals(FirstActivity.class) {
// try without runOnUiThread if it will not help
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
new InitializatioTask().execute();
}
});
}
}
@Override
public void onActivityStarted(Activity activity) {
}
@Override
public void onActivityResumed(Activity activity) {
}
@Override
public void onActivityPaused(Activity activity) {
}
@Override
public void onActivityStopped(Activity activity) {
}
@Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
}
@Override
public void onActivityDestroyed(Activity activity) {
}
});
回答by Vickyexpert
As you are already aware why this white screen is there, as due to background processes or application initialization or large files, so just check below idea for overcome from this.
由于您已经知道为什么会出现这个白屏,因为后台进程或应用程序初始化或大文件,因此请查看以下想法以克服此问题。
To prevent this white screen on beginning of the app, one way is splash screen, this is just a way not final and you must have to use.
为了防止应用程序开始时出现此白屏,一种方法是启动画面,这只是一种非最终方法,您必须使用。
When you will show splash screen from your splash.xml file, then also this issue will be remain same,
当您从 splash.xml 文件显示启动画面时,此问题也将保持不变,
So you have to create ont style in style.xml file for splash screen and there you have to set window background as your splash image and then apply that theme to your splash activity from manifest file. So now when you will run app, first it will set theme and by this way user will be able to see directly splash image instead of white screen.
因此,您必须在 style.xml 文件中为启动画面创建 ont 样式,并且必须将窗口背景设置为启动图像,然后将该主题应用于清单文件中的启动活动。所以现在当你运行应用程序时,首先它会设置主题,这样用户将能够直接看到启动图像而不是白屏。
回答by Michele La Ferla
Within the lifecycle callback methods, you can declare how your activity behaves when the user leaves and re-enters the activity. Remember that the way Android is designed, there is a lifecycle for each and every app. If you put too much load to the onCreate()
method (which is the method used to load the layout files and initalise any controls you have in it), then the white screen will become more visible, as the layout file will take longer to load.
在生命周期回调方法中,您可以声明您的 Activity 在用户离开和重新进入 Activity 时的行为方式。请记住,Android 的设计方式是,每个应用程序都有一个生命周期。如果您对该onCreate()
方法施加过多负载(该方法用于加载布局文件并初始化您在其中的任何控件),那么白屏将变得更加明显,因为加载布局文件需要更长的时间。
I suggest using several different methods when starting an activity. Such are the onStart()
(being called as the first thing once the app is loaded), onActivityCreated()
(being called after the layout is displayed and useful if you are making any data processing upon starting the activity).
我建议在开始活动时使用几种不同的方法。这就是onStart()
(在加载应用程序后作为第一件事调用),onActivityCreated()
(在布局显示后调用,如果您在启动活动时进行任何数据处理,则很有用)。
To make it easier for you, below is the official activity lifecycle diagram:
为了方便您,下面是官方的活动生命周期图:
回答by gmetal
Have you tried setting theandroid:windowBackground
attribute in the theme of your launcher activity, to either a color or a drawable?
您是否尝试将android:windowBackground
启动器活动主题中的属性设置为颜色或可绘制对象?
For example this:
例如这个:
<item name="android:windowBackground">@android:color/black</item>
when added to the Launcher activity theme will show a black color (rather than the white color) on startup. This is an easy trick to hide long initialisation, while showing your users something, and it works fineeven if you subclass the Application object.
当添加到 Launcher 活动主题时,将在启动时显示黑色(而不是白色)。这是隐藏长初始化的一个简单技巧,同时向您的用户展示一些东西,即使您对 Application 对象进行子类化,它也能正常工作。
Avoid using other constructs (even Threads) for doing long initialisation tasks, because you may end up not being able to control the lifecycle of such constructs. The Application object is the correct place for doing exactly this type of actions.
避免使用其他构造(甚至线程)来执行长时间的初始化任务,因为您最终可能无法控制此类构造的生命周期。Application 对象是执行此类操作的正确位置。
回答by Hitesh Singh
please add this line into your app theme
请将这一行添加到您的应用主题中
<item name="android:windowDisablePreview">true</item>
for more information : https://developer.android.com/topic/performance/vitals/launch-time#themed
欲了解更多信息:https: //developer.android.com/topic/performance/vitals/launch-time#themed
回答by Sohail Zahid
Both properties works
两个属性都有效
<style name="AppBaseThemeDark" parent="@style/Theme.AppCompat">
<!--your other properties -->
<!--<item name="android:windowDisablePreview">true</item>-->
<item name="android:windowBackground">@null</item>
<!--your other properties -->
</style>
回答by Javier Reinoso
Just write the item in values/styles.xml:
只需在 values/styles.xml 中写入项目:
<item name="android:windowBackground">@android:color/black</item>
For example, in the AppTheme:
例如,在 AppTheme 中:
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="windowNoTitle">true</item>
<item name="windowActionBar">false</item>
<item name="android:windowFullscreen">true</item>
<item name="android:windowContentOverlay">@null</item>
<item name="android:windowBackground">@android:color/black</item>
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
回答by Hiren Patel
I had same issue, you have to update your style.
我有同样的问题,你必须更新你的风格。
style.xml
样式文件
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Customize your theme here. -->
<item name="drawerArrowStyle">@style/DrawerArrowStyle</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowDisablePreview">true</item>
<item name="android:windowBackground">@null</item>
<item name="android:windowIsTranslucent">true</item>
</style>
Your manifest file should looks like below.
您的清单文件应如下所示。
<application
android:name=".MyApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme">
// Other stuff
</application>
Outout:
输出:
Hope this would help you.
希望这会帮助你。