App冷启动白屏/黑屏问题分析及解决方案

来源:互联网 发布:plsql怎么导出表数据 编辑:程序博客网 时间:2024/05/16 01:29

一、问题背景

最近在做产品首次启动页优化功能时,发现在点击启动launch图标与切换到子进程页面时会白屏或黑屏一段时间,时间长短根据不同机型性能不一。

原来看过相关文章,借此机会总结一下app启动的闪屏页面是怎么产生的,该如何优化?

二、问题分析

既然我们想要优化app启动速度,那我们肯定要了解app启动的几种模式:冷启动(Cold start),热启动(Warm start),温启动(Lukewarm start)。

只有冷启动是从头开始,其他两种是将应用从后台切换到前台。所以我们基于冷启动的情况进行优化。这样做也可以提高热启动与温启动的性能。

冷启动(Cold start):

在冷启动的时候,系统会开始三个任务:
1. 加载并且启动app
2. 在启动后立即显示一个应用程序的空白窗口(这就是弹出的白屏)
3. 创建app进程

当系统创建应用程序进程,应用程序进程将负责下一阶段。这些阶段是:
1. 创建app 对象
2. 启动主线程
3. 创建主activity
4. inflating views
5. Laying out the screen
6. 执行首次绘制

一旦应用进程完成了首次绘制,系统进程就会替换掉当前显示的背景窗口(白屏/黑屏),将其替换为activity的背景窗口。此时,用户可以开始使用应用程序。下图是冷启动过程流程图:
冷启动流程

热启动(Warm start):

与冷启动相比,热启动应用程序要简单得多,开销更低。在热启动,所有的系统都是把你的activity切换到前台。如果应用程序的activity仍驻留在内存中,那么app不会重复对象初始化,inflating views和重新渲染。

热启动显示与冷启动场景相同的屏幕行为:先显示空白屏幕,直到应用程序完成再渲染activity。

温启动(Lukewarm start):

用户退出您的应用,但随后重新启动它。该过程可能已继续运行,但应用程序必须通过调用onCreate()从头开始重新创建activity,这就是典型的温启动。

三、问题解决
通过对以上几种启动模式的了解,我们知道冷启动这种模式肯定是最耗时的,也是最需要进行优化的。那么该如何优化呢?

根据上面对冷启动的分析可以知道,在系统创建进程之前系统会读取当前Activity的Theme绘制一个空白窗体,这个空白窗体主要是为了立即给用户点击反馈。

第一种方法(不推荐):

在activity的theme中设置

<item name="android:windowDisablePreview">true</item>//设置这个属性可以关闭系统弹出的空白窗体

<item name="android:windowIsTranslucent">true</item><item name="android:windowNoTitle">true</item>//将activity theme设置为透明也可以让用户不可见空白窗体

上面两种都可以通过取消、透明化系统的空白窗体页面来达到启动的“加速”

不过上面两种设置会造成一个问题:当用户点击启动activity后,界面无响应。用户只能等待初始化完成,这段时间无法交互,用户体验很差,不推荐。

第二种方法(推荐):
既然是读取Theme,那我们可以在这里做文章。

我们自定义一个启动style用来给用户友好的反馈,当activity绘制之前将真正的style还原回去。具体是利用style中的android:windowBackground属性:

  • 先定义一个drawable,可以使用纯色背景,图片等。
    Layout XML file:
<?xml version="1.0" encoding="utf-8"?><layer-list xmlns:android="http://schemas.android.com/apk/res/android"            android:opacity="opaque">    <item android:drawable="@android:color/white"/>    <item>        <bitmap            android:gravity="center"            android:src="@drawable/launch_logo"/>    </item></layer-list>
  • 在style中定义一个launchStyle,设置android:windowBackground为我们刚刚定义的drawable
    style file:
<style name="LaunchStyle" parent="BaseAppTheme">    <item name="android:windowBackground">@drawable/launch_view</item></style>
  • 在activity中设置我们的launchStyle。
    Manifest file:
<activity    android:name=".MyMainActivity"    ...    android:theme="@style/LaunchStyle"/>

这样在我们冷启动我们的app时,看到的不再是空白页面(白屏/黑屏)而是我们自定义的界面了,展示更友好。

这样还没结束还差最后一步也是最重要的一步,在Activity加载真正的界面之前,将Theme设置回正常的Theme。

public class MyMainActivity extends AppCompatActivity {  @Override  protected void onCreate(Bundle savedInstanceState) {    setTheme(R.style.BaseAppTheme);    super.onCreate(savedInstanceState);    // ...  }}

注意: setTheme(R.style.BaseTheme) 一定要在 super.onCreate() 与 setContentView(): 之前调用

三、问题总结

上面通过Theme的解决方法只是一种交互上的友好提速,我们还是要花费更多的精力在真正的性能调优上:优化布局,避免大量对象初始化,延迟初始化,界面预加载,多线程加载等。
App启动速度是一个App是否优秀很重要的标志,我们应该不断的提升,优化。

参考链接:https://developer.android.com/topic/performance/launch-time.html

0 0