Android APP启动存在的问题
细心的同学会发现,点击安卓手机桌面上的图标时,有时候应用马上进入主界面,有时候要经历好几秒甚至更久的白屏或者黑屏时间才能进入主界面,这就是安卓应用常见的冷热启动问题。
Android APP启动方式
先来看下Google官方文档 Launch-Time Performance 对应用启动方式的概述。
安卓应用的启动方式分为三种:冷启动、暖启动和热启动;不同的启动方式决定了应用UI对用户可见所花费的时间不同,冷启动花费的时间最长。
1.冷启动
冷启动指的是应用程序从头开始:系统的进程没有,直到此开始,创建了应用程序的进程。 在应用程序自设备启动以来第一次启动或系统杀死应用程序等情况下会发生冷启动。 这种类型的启动在最小化启动时间方面是最大的挑战,因为系统和应用程序比其他启动状态具有更多的工作。
2.暖启动
当应用中的Activity被销毁,但在内存中常驻时,应用的启动方式就会变为暖启动。相比冷启动,暖启动过程减少了对象初始化、布局加载等工作,启动时间更短。但启动时,系统依然会展示一个空白背景,直到第一个Activity的内容呈现为止。
3.热启动
相比暖启动,热启动时应用做的工作更少,启动时间更短。热启动产生的场景很多,常见如:用户使用返回键退出应用,然后马上又重新启动应用。
为什么会出现白屏
冷启动白屏的持续时间可能会很长,这是一个很糟糕的体验,它的启动速度由以下引起:
-
Application的onCreate()方法,对于大型的APP来说,通常会在这里做大量的通用组件的初始化操作;建议:很多第三方SDK都放在Application初始化,我们可以放到用到的地方才进行初始化操作。 -
Activity的onCreate()流程,特别是UI的布局与渲染操作,如果布局过于复杂很可能导致严重的启动性能问题;建议:Activity仅初始化那些立即需要的对象,xml布局减少冗余或嵌套布局。
优化方案
优化方案主要是从主题上着手
1.直接干掉Activity启动界面
- 定义一个style:
<style name="AppTheme.Launcher">
<!--关闭启动窗口-->
<item name="android:windowDisablePreview">true</item>
</style>
- 在
AndroidManifest.xml文件中引用定义好的style:
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:theme="@style/AppTheme.Launcher">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
- 最后在
MainActivity里回复正常主题:
public class MainActivity extends BaseActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setTheme(R.style.AppTheme);
setContentView(R.layout.activity_main);
}
}
这样启动APP,就没有白屏了,但会出现点击图标,应用半天没有反应的现象,显然不好,很多APP把这一个闪屏当做一个广告页、品牌宣传的页面。
2.Google针对APP闪屏,在Material Design规范 launch-screens,也给出了非常详细的设计定义,有两种方案。
- 品牌展示
上图提供了一个品牌宣传图片也可以是广告页,来看看如何实现的,定义一个style:
<style name="AppTheme.Launcher">
<item name="android:windowBackground">@drawable/branded_launch_screens</item>
</style>
branded_launch_screens.xml文件内容
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"
android:opacity="opaque">
<!-- android:opacity=”opaque”参数是为了防止在启动的时候出现背景的闪烁。 -->
<!--黑色背景颜色-->
<item android:drawable="@android:color/black" />
<!-- 产品logo-->
<item>
<bitmap
android:gravity="center"
android:src="@mipmap/empty_image01" />
</item>
<!-- 右上角的图标元素 -->
<item>
<bitmap
android:gravity="top|right"
android:src="@mipmap/github" />
</item>
<!--最下面的文字-->
<item android:bottom="50dp">
<bitmap
android:gravity="bottom"
android:src="@mipmap/ic_launcher" />
</item>
</layer-list>
或者直接在style文件里直接替换闪屏页
<style name="AppTheme.Launcher">
<item name="android:windowFullscreen">true</item>
<item name="android:windowBackground">@mipmap/app_welcome</item>
</style>
- 主页预加载
上图提供了一个与界面面布局占位一样的内容,给用户感觉已经在加载中了。先定义一个style:
<style name="AppTheme.Launcher">
<item name="android:windowBackground">@drawable/placeholder_ui</item>
</style>
placeholder_ui文件内容:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"
android:opacity="opaque">
<!--状态栏颜色-->
<item android:drawable="@color/colorPrimaryDark" />
<!--假装这里是个toolbar-->
<item
android:drawable="@color/colorPrimary"
android:top="25dp" />
<!--状态栏25+toolbar56=距离top81-->
<item
android:drawable="@android:color/white"
android:top="81dp" />
</layer-list>