Android APP启动优化一 APP启动测量

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qiyei2009/article/details/86843924

1 前言

Android APP 启动优化是性能优化的重要方向之一,特别是对于原生应用来讲,控制在1s内以内对一个APP的竞争力很重要,下面从几个角度来讲APP的启动优化,先看APP的启动类别

2 APP启动类别

参考google官方文档App startup time,官方对APP启动主要做了三种分类

1.冷启动

冷启动指的是APP从头开始启动,没有创建进程,需要完整的走进程创建,ActivityThread创建,Application创建等生命周期的启动,冷启动耗时最多
启动时分为以下几步
1 加载和启动app
2 加载空白window
3 创建App进程

随后进行如下步骤
1 创建Application对象,并回调其方法
2 启动主线程
3 创建MainActivity
4 初始化View和加载布局
5 布局屏幕
6 首帧绘制
冷启动一般流程如下:
在这里插入图片描述

2.暖启动

当应用中的Activity被销毁,但在内存中常驻时,应用的启动方式就会变为暖启动。相比冷启动,暖启动过程减少了对象初始化、布局加载等工作,启动时间更短。但启动时,系统依然会展示一个空白背景,直到第一个Activity的内容呈现为止。因此暖启动一般会走Activity的onCreate生命周期,暖启动耗时较少,一般需要注意在Activity的生命周期中不要做耗时操作即可。

3.热启动

相比暖启动,热启动时应用做的工作更少,启动时间更短。热启动产生的场景很多,常见如:用户使用返回键退出应用,然后马上又重新启动应用。热启动较快,一般需要注意在onResmue中不要做耗时操作

对于系统流程我们一般无法改变,因此对于三方应用来说,APP启动优化的主要方向在Application的生命周期和Activity的生命周期中

3 APP启动测量

前面讲了APP启动的类别,现在要讲如何粗略或者详细的测量一个APP的启动时间,一般来说有以下几种办法

1 adb 命令测量

adb shell am start –W packageName/首屏Activity
例如:

adb shell am start –W com.qiyei.mall/com.qiyei.mall.ui.activity. MainActivity

执行如下:
在这里插入图片描述
MainActivity 是首页,HomeActivity是主页

ThisTime: 最后一个Activity启动耗时
TotalTime: 启动所有Activity耗时
WaitTime: AMS启动Activity耗时

2 ActivityManager中日志打印

ActivityManager中会打印启动activity的时间

ActivityManager: Displayed com.android.myexample/.StartupTiming: +3s534ms (total +1m22s643ms)

相关的代码如下:
ActivityRecord#reportLaunchTimeLocked()

    private void reportLaunchTimeLocked(final long curTime) {
        final ActivityStack stack = getStack();
        if (stack == null) {
            return;
        }
        final long thisTime = curTime - displayStartTime;
        final long totalTime = stack.mLaunchStartTime != 0
                ? (curTime - stack.mLaunchStartTime) : thisTime;
        if (SHOW_ACTIVITY_START_TIME) {
            Trace.asyncTraceEnd(TRACE_TAG_ACTIVITY_MANAGER, "launching: " + packageName, 0);
            EventLog.writeEvent(AM_ACTIVITY_LAUNCH_TIME,
                    userId, System.identityHashCode(this), shortComponentName,
                    thisTime, totalTime);
            StringBuilder sb = service.mStringBuilder;
            sb.setLength(0);
            sb.append("Displayed ");
            sb.append(shortComponentName);
            sb.append(": ");
            TimeUtils.formatDuration(thisTime, sb);
            if (thisTime != totalTime) {
                sb.append(" (total ");
                TimeUtils.formatDuration(totalTime, sb);
                sb.append(")");
            }
            Log.i(TAG, sb.toString());
        }
        mStackSupervisor.reportActivityLaunchedLocked(false, this, thisTime, totalTime);
        if (totalTime > 0) {
            //service.mUsageStatsService.noteLaunchTime(realActivity, (int)totalTime);
        }
        displayStartTime = 0;
        stack.mLaunchStartTime = 0;
    }

可以看到打印的是,这个时间从应用启动(创建进程)开始计算,到完成视图的第一次绘制的时间

3 手动打点

这个思想也比较简单,由于应用层能接触到的最早方法是Application#attachBaseContext()而结束时间,我们可以认为是Activity#onWindowFocusChanged或者View的真正绘制完成,因此我们可以在attachBaseContext记录一下时间,在onWindowFocusChanged中或者View绘制完成后记录结束时间,只是需要注意怎么处理View的onDraw监听问题

4 Systrace测量

这个可以参考官方文章systrace来进行操作,注意systrace需要python环境,因此需要先搭建好python环境。下面是一个systrace的例子
在这里插入图片描述
可以看到,systrace可以看到更多的系统调用过程,例如这里可以看到进程Zygote创建和ActivityThread的初始化时间等,有助于分析启动时当时系统的状态。

这一篇就介绍到这,下一篇会介绍TraceView和Systrace的简单使用

猜你喜欢

转载自blog.csdn.net/qiyei2009/article/details/86843924