App冷启动
App启动的方式有很多种,开发人员可以优化的一般都是冷启动方式。
- 冷启动 : 在App没有被创建的情况下启动,这个过程中会创建进程,启动Application,然后启动主Activity。
- 冷启动时间 : 一般控制在2,3,5秒(2秒正常,3秒凑合,5秒快到用户忍受极限了)。
本篇讨论的应用场景
在实际开发中,有些App的启动过程中只有一个Activity,也就是AndroidManifest.xml里面有标签为
action android:name=”android.intent.action.MAIN”的Activity就是最终的首页,这种情况计算启动时间比较方便,使用命令行方式统计就可以解决。而有的App启动过程中有多个Activity,比如说先进行一些初始化操作或者动画播放完毕再进入到首页的情况,本篇文章要讨论就是这种情况。多个Activity的情况用命令行去测量每个Activity的时间,然后再加起来,结果是不够准确的,也不是用户感知的时间。所以本篇讨论的计算方法适用如下场景:
- 启动过程中不止有一个Activity。
- 测量的不是真正概念上冷启动的时间,而是从用户感知的角度,由创建进程到真正首页显示的时间。
- 不用执行命令行进行计算,而是写代码进行起始时间点之间的计算。
启动过程有多个Activity的计算方法
App启动流程需要创建进程,启动Application,以及Activity,要测量这部分的时间。通过了解App的启动流程,找出以下测量的起始时间点:
- 在Application的attachBaseContext()开始计算第一部分的启动时间,在第一个Activity的onCreate()中结束计算,这个为Application启动时间,在下面的实例代码中用coldTime表示
- 在第一个Activity的onCreate()中开始计算第二部分时间,在下面示例代码中用hotTime表示,然后在真正的首页Activity的 onWindowFocusChanged()中结束计算。
- 总的时间就是coldTime+hotTime的总和
代码
废话不多说,直接上代码。
为了测量方便,首先写一个计算时间的类
import java.util.HashMap;
public class TimeUtils {
private static HashMap<String, Long> sCalTimeMap = new HashMap<>();
public static final String COLD_TIME = "cold_time";
public static final String HOT_TIME = "hot_time";
public static long sColdTime = 0;
/**
* 记录某个事件的开始时间
* @param key 事件名称
*/
public static void beginTimeCalculate(String key) {
long currentTime = System.currentTimeMillis();
sCalTimeMap.put(key, currentTime);
}
/**
* 获取某个事件的运行时间
*
* @param key 事件名称
* @return 返回某个事件的运行时间,调用这个方法之前没有调用 {@link #beginTimeCalculate(String)} 则返回-1
*/
public static long getTimeCalculate(String key) {
long currentTime = System.currentTimeMillis();
Long beginTime = sCalTimeMap.get(key);
if (beginTime == null) {
return -1;
} else {
sCalTimeMap.remove(key);
return currentTime - beginTime;
}
}
/**
* 清除某个时间运行时间计时
*
* @param key 事件名称
*/
public static void clearTimeCalculate(String key) {
sCalTimeMap.remove(key);
}
/**
* 清除启动时间计时
*/
public static void clearStartTimeCalculate() {
clearTimeCalculate(HOT_TIME);
clearTimeCalculate(COLD_TIME);
sColdTime = 0;
}
写好工具类,就开始将计算时间的代码写入,以下的Log打印代码是为了测试方便而写,可以忽略它。
第一步:在Application的attachBaseContext()方法中添加代码:
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
if(是主进程){//要在主进程才可以
TimeUtils.beginTimeCalculate(TimeUtils.COLD_TIME);//这句
Log.e("beginTimeCalculate","开始记录冷启动时间");
}
}
}
第二步:在第一个Activity的onCreate()方法中执行如下代码
private void calculateStartTime() {
long coldTime = TimeUtils.getTimeCalculate(TimeUtils.COLD_TIME);
Log.e("coldTime","冷启动时间"+coldTime);
// 这里记录的TimeUtils.sColdTime是指Application启动的时间
TimeUtils.sColdTime = coldTime > 0 ? coldTime : 0;
TimeUtils.beginTimeCalculate(TimeUtils.HOT_TIME);//开始计算hotTime
}
第三步:在真正的首页Activity的onWindowFocusChanged()方法添加以下代码:
@Override
public void onWindowFocusChanged(boolean hasFocus) {
//这段代码在没有经过广告页或引导页的情况下去执行,可以在if判断的条件加上去
if (hasFocus) {
long hotTime = TimeUtils.getTimeCalculate(TimeUtils.HOT_TIME);
Log.e("hotStartTime","热启动时间"+hotTime);
if (TimeUtils.sColdTime > 0 && hotTime > 0) {
// 真正的冷启动时间 = Application启动时间 + hotTime
long coldTotalTime = TimeUtils.sColdTime + hotTime;
Log.e("coldTotalTime","冷启动时间"+coldTotalTime);
// 过滤掉异常启动时间
if (coldTotalTime < 50000) {
// 上传冷启动时间coldTotalTime
}
} else if (hotTime > 0) {
// 过滤掉异常启动时间
if (hotTime < 30000) {
// 上传热启动时间hotStartTime
}
}
}
}
写好代码运行,看Log打印,就能知道启动时间的耗时。以上是需要在正常情况下启动App,其它异常情况不在讨论范围。每次测量也会存在一定的偏差,需要测量多次取平均值。测量启动时间基本都会存在大概20%的不准确率,但是我们还是可以通过这个时间,去确定需不需要进行优化。
知道启动时间就利于我们去优化App的启动时间,也许就是因为优化了1s,就能赢得更多用户的停留,也是技术上的进步和对项目的负责,一起行动起来吧。
作者:honey饼
链接:https://juejin.im/post/5e005d5151882512360d6413
转载请注明:Android开发中文站 » 计算App冷启动时间