社区微信群开通啦,扫一扫抢先加入社区官方微信群
社区微信群
在安卓系统上,应用在没有进程的情况下,应用的启动都是这样一个流程:当点击app的启动图标时,安卓系统会从Zygote进程中fork创建出一个新的进程分配给该应用,之后会依次创建和初始化Application类、创建MainActivity类、加载主题样式Theme中的windowBackground等属性设置给MainActivity以及配置Activity层级上的一些属性、再inflate布局、当onCreate/onStart/onResume方法都走完了后最后才进行contentView的measure/layout/draw显示在界面上,所以直到这里,应用的第一次启动才算完成。
所以,应用的启动流程如下:
Application的构造器方法——>attachBaseContext()——>onCreate()——>Activity的构造方法——>onCreate()——>配置主题中背景等属性——>onStart()——>onResume()——>测量布局绘制显示在界面上。
应用的启动分为冷启动、热启动、温启动,而启动最慢、挑战最大的就是冷启动:系统和App本身都有更多的工作要从头开始!
1、冷启动:当启动应用时,后台没有该应用的进程,这时系统会首先会创建一个新的进程分配给该应用,这种启动方式就是冷启动。
2、热启动:当启动应用时,后台已有该应用的进程,比如按下home键,这种在已有进程的情况下,这种启动会从已有的进程中来启动应用,这种启动方式叫热启动。
3、温启动 :当启动应用时,后台已有该应用的进程,但是启动的入口Activity被干掉了,比如按了back键,应用虽然退出了,但是该应用的进程是依然会保留在后台,这种启动方式叫温启动。
应用在冷启动时,要执行三个任务:
而这三个任务执行完毕之后会马上执行以下任务:
而一旦App进程完成了第一次绘制,系统进程就会用Main Activity替换已经展示的Background Window,此时用户就可以使用App了。
Google官方文档对应用启动优化的概述《Launch-Time Performance》。
应用启动时,由于启动缓慢导致的黑屏、白屏,对于这种问题我们可以在等待第一帧显示的时间里,加入一些配置以增加体验,比如加入Activity的background,这个背景会在显示第一帧前提前显示在界面上。
1、先为主界面单独写一个主题style,设置一张待显示的图片,这里我设置了一个颜色,然后在manifest中设置给MainActivity:
<style name="AppTheme.Launcher">
<item name="android:windowBackground">@drawable/bg_color</item>
</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>
2、然后在MainActivity中加载布局前把AppTheme重新设置给MainActivity:
@Override
protected void onCreate(Bundle savedInstanceState) {
setTheme(R.style.AppTheme);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
这样在启动时会先显示background,然后待界面绘制完成再显示主界面
作为普通应用,App进程的创建等环节我们是无法主动控制的,可以优化的也就是Application、Activity创建以及回调等过程。
一般会拖慢启动速度的操作
Heavy activity initialization
Heavy app initialization
优化策略
1、数据库及IO操作都移到工作线程,并且设置线程优先级为THREAD_PRIORITY_BACKGROUND,这样工作线程最多能获取到10%的时间片,优先保证主线程执行。
new Thread(new Runnable() {
@Override
public void run() {
//设置线程优先级,不与主线程抢资源
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
//...
}
}).start();
2、流程梳理,延后执行
考虑一些操作逻辑顺序上是否可以调整,过重的操作延迟初始化,或者用到的时候再初始化。去除重复的无用的操作。
懒加载方式:
getWindow().getDecorView().post(new Runnable() {
@Override
public void run() {
myHandler.post(mLoadingRunnable);
}
});
在窗口完成以后进行加载,这里面的run方法是在onResume之后运行。
通过ADB命令统计应用的启动时间:
adb shell am start -W [packageName]/[packageName.MainActivity]
执行成功后将返回三个测量到的时间:
使用TraceView 从代码层面分析性能问题,针对每个方法来分析,比如当我们发现我们的应用出现卡顿的时候,我们可以来分析出现卡顿时在方法的调用上有没有很耗时的操作,通过TraceView,可以得到两种数据。
使用TraceView做热点分析,找出最需要优化的点。关于TrackView的具体使用可查阅相关资料。
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!