目录
2.3、Allpication,ContentProvider优化
2.4.3、异步加载布局AsyncLayoutInflater
一、介绍
1.1、冷启动和热启动
- 冷启动:当启动应用时,后台没有该应用的进程,这时系统会重新创建一个新的进程分配给该应用,然后再根据启动的参数,启动对应的进程组件,这个启动方式就是冷启动
- 热启动:当启动应用时,后台已有该应用的进程(例:按back键、home键,应用虽然会退出,但是该应用的进程是依然会保留在后台,可进入任务列表查看),所以在已有进程的情况下,这种启动会从已有的进程中来启动对应的进程组件,这个方式叫热启动
1.2、启动速度测量
1.2.1、TraceCompat
- TraceCompat.beginSection(“xxx”);// 手动埋点起始点
- TraceCompat.endSection();// 手动埋点结束点
- python systrace.py -b 32768 -t 5 -a packageName -o trace.html sched gfx view wm am app
- 使用python命令生成报告
- cd到Android/sdk/platform-tools/systrace
- 执行python命令,python环境没有配置好的话可使用Home Brew install一下
- python systrace.py -b 32768 -t 10 -a 包名 -o browser.html sched gfx view wm am app
- adb shell am start -w 包名/类名
返回的结果,就是标准的应用程序的启动时间
- ThisTime:最后一个Activity启动耗时;
- TotalTime:启动时经历的所有Activity启动耗时;
- WaiteTime:AMS启动所有Activity的总时间
- startTime记录的刚准备调用startActivityAndWait()的时间点
- endTime记录的是startActivityAndWait()函数调用返回的时间点
- WaitTime = startActivityAndWait()调用耗时。
二、优化方式
应用进程不存在的情况下,从点击桌面应用图标,到应用启动(冷启动),会经历以下流程:
- Launcher startActivity
- AMS startActivity
- Zygote fork 进程
- ActivityThread main()
- ActivityThread.attach
- handleBindApplication
- Application.attachBaseContext
- ContentProvider.installContentProviders
- Application.onCreate
- ActivityThread 进入loop循环
- Activity生命周期回调,onCreate、onStart、onResume...
2.1、MultiDex启动优化
目前 Android 5.0 以上的设备已经自身支持了 MultiDex 功能,也就是说在安装 apk 的时候,系统已经会帮我们把 apk 里面的所有 dex 文件都做好 Optimize 处理,所以不需要我们在代码里启用 MultiDex 了。但是对于 Android 5.0 以下的设备,依然要求我们启用 MultiDex。而这些系统的设备在第一次运行 App 的时候,需要对所有的 Secondary Dexes 文件都进行一次解压以及 Optimize 处理(生成 odex 文件),这段时间会有明显的耗时,所有会产生明显的卡顿现象。
配置:
android {
defaultConfig {
...
multiDexEnabled true // Enable MultiDex.
//定义main dex中必须保留的类
multiDexKeepProguard file('mainDexClasses.pro')
...
}
...
}
dependencies {
implementation 'androidx.multidex:multidex:2.0.0'
}
1、在Application的attachBaseContext启动新进程执行dexOpt
protected void attachBaseContext(Context base) {
// 只有5.0以下需要执行 MultiDex.install
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
MULTI_DEX = MULTI_DEX + "_" + getVersionCode(base);
if (SystemUtil.isInMainProcess(base)) {
// 判断有没有执行过dexOpt
if (!dexOptDone(base)) {
preLoadDex(base);
}
}
if (!KwaiApp.isMultiDeXProcess(base)) {
MultiDex.install(base);
}
}
super.attachBaseContext(base);
}
/**
* 是否进行过DexOpt操作。
*
* @param context
* @return
*/
private boolean dexOptDone(Context context) {
SharedPreferences sp = context.getSharedPreferences(MULTI_DEX, MODE_MULTI_PROCESS);
return sp.getBoolean(MULTI_DEX, false);
}
/**
* 在单独进程中提前进行DexOpt的优化操作;主进程进入等待状态。
*
* @param base
*/
public void preLoadDex(Context base) {
// 在新进程中启动PreLoadDexActiv