App的启动被分成了:
- 冷启动:系统没有为该程序创建进程,程序从头开始启动;例如,安装后第一次启动,应用程序被系统完全终止之后再打开。
- 热启动:此程序仍然留在内存中,只是被系统从后台带到前台,可避免重复对像初始化和避免重复加载和渲染;例如,使用home键退到桌面,再重新启动。
- 暖启动:包含了冷启动和热启动的部分操作,消耗比热启动多一些,与热启动的区别在于,它启动时会调用onCreate方法,相当于是介于冷启动和热启动之间的情况;例如,使用back键退出应用并重新启动。
因为冷启动的流程,会先加载并启动app,启动后会马上显示一个空白窗口,然后再创建app进程,创建launchActivity,加载和绘制布局。
这个过程中我们能优化处理的部分就是:
- 空白窗口
- Application的onCreate方法
- launchActivity的onCreate,onStart,onResume方法
注意:如果在Application和launchActivity的以上方法中有启动其他activity的,那么启动的这个activity的onCreate,onStart,onResume方法也需要优化
黑白屏优化
这个空白窗口在有些主题下是白色有些主题下是黑色,这样就出现了黑白屏的问题。
如果app启动的过程中,有耗时操作或者性能差一些的手机,这个黑白屏的显示时间就会让用户感知到,影响体验,而我们能对这个空白窗口的样式进行改变,变成我们启动页的样式或者大体和启动页的样式一致,这样我们就比较优雅的解决了黑白屏的问题。
还有对于直接使用将背景透明化的也不太合适,因为这样会使用户感觉点了app之后没有响应,这段时间也是和启动时是否耗时和手机性能有关,所以这样的处理并不优雅,也违背了google的设计。
知道原理之后其实就很简单:
- 设置启动主题
<style name="LauncherTheme" parent="AppTheme">
<item name="android:windowBackground">@drawable/launcher_bg</item>
<item name="android:windowFullscreen">true</item>
</style>
- 配置LauncherActivity
<activity
android:name=".LauncherActivity"
android:theme="@style/LauncherTheme">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
- LauncherActivity布局背景也设置成launcher_bg
<RelativeLayout
...
android:background="@drawable/launcher_bg"
>
</RelativeLayout>
launcher_bg例如:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@color/colorAccent" />
<item android:top="150dp">
<bitmap
android:gravity="top"
android:src="@drawable/ic_launcher" />
</item>
</layer-list>
这里有点讲究,设计最好启动页使用纯色的背景和简单的icon处理,这样方便代码设置颜色,避免直接使用一张很大的图,也影响性能。
- LauncherActivity中启动MainActivity逻辑:
postDelayed(new Runnable() {
@Override
public void run() {
startActivity(new Intent(LauncherActivity.this, MainActivity.class));
LauncherActivity.this.finish();
}
}, 2000);
例如这里的简单延时两秒启动过MainActivity。
代码优化
黑白屏结局之后,我们再来看看代码的优化,其实代码的优化,只需要知道在哪些点上去检测,然后尽量不要做耗时操作即可。
-
优化的点:
- Application的onCreate方法
- 第一个启动的Activity的onCreate,onStart,onResume方法
对于这个优化,我们直接看有可能不那么直观,Android中也提供了分析工具,可以检测app启动时间,以onCreate方法为例:
@Override
public void onCreate() {
super.onCreate();
File file = new File(Environment.getExternalStorageState(), "app.trace");
Debug.startMethodTracing(file.getAbsolutePath());
//业务逻辑
Debug.stopMethodTracing();
}
这里在app.trace文件中就保存下来了业务逻辑部分执行的时间,通过
adb pull /storage/emulated/0/app.trace
这个命令就能得到app.trace文件,然后放到Android Studio中就能看到,业务逻辑部分哪些方法执行了多少时间,我们就能针对优化了。
-
优化的方式
- 异步线程方式,前提:对异步要求不高
- 懒加载的方式,用的时候再初始化
具体的方式还是需要根据具体业务处理。
UI渲染优化
代码优化部分处理完了之后,我们还有就是UI布局的优化,其中就涉及到过度绘制问题,因为gpu的绘制完全根据cpu的指令来的,所以只要我们UI布局有重复绘制的部分,gpu依然会重复绘制,而这部分就是可以优化的,这也是导致过度绘制的原因。
优化的点包括:
- 布局的背景是否重复,或者是否合理(原则:尽量不在相同区域重复设置背景)
- 是否可以减少UI布局的层级
- 自定义View绘制是否包含覆盖
- 使用merge标签排除相同ViewGroup容器
- 使用ViewStub进行布局的懒加载,在需要显示的时候再使用inflater加载