启动与基线配置文件
加快冷启动速度
启动与基线配置文件 是 CoddyKit 上的免费 Android Academy 课时。 这是第 4 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Android Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Android Academy 课程共包含 4 节课。
第一印象:应用启动
启动时间是每位用户最先感受到的事情。Google Play 甚至会将启动缓慢列为质量问题。快速冷启动会让应用显得高级;启动缓慢则会让用户离开。
在本课中,您将学习三种启动类型、启动变慢的原因,以及能显著加快冷启动速度的现代工具——应用启动库和基线配置文件。
冷启动、温启动与热启动
Android 定义了三种启动场景,速度从慢到快依次为:
- 冷启动:进程不存在。Android 创建进程,运行
Application,然后显示您的第一个屏幕。这是最慢、也最需要优化的启动方式。 - 温启动:进程仍然存活,但必须重新创建 Activity。
- 热启动:Activity 仍在内存中,只需将其调到前台。几乎可以立即完成。
优化重点应放在冷启动上,因为新用户和回访用户最常遇到这种启动。
测量启动时间
无法改进未测量的内容。这里有两种简单方法:
- Logcat:系统会记录一行
Displayed,其中包含从启动到显示第一帧所需的时间。 - Macrobenchmark:
StartupTimingMetric可提供稳定且可重复的冷启动数据。
运行下面的 adb 命令,并查找 Displayed 行。
# Cold-start the app and log time to first frame
adb shell am start -W -S com.example.app/.MainActivity
# Output includes:
# TotalTime: 412 <- ms to first frame
# Or filter logcat:
adb logcat | grep "Displayed com.example.app"保持 Application.onCreate 轻量
Application.onCreate() 中的所有内容都会在主线程上、在第一帧显示之前运行。繁重的初始化会直接延迟启动。
下面的错误版本会急切地初始化多个库。对于第一屏不需要的内容,请延迟初始化或放到后台执行。
// SLOW: blocks the first frame with eager init
class MyApp : Application() {
override fun onCreate() {
super.onCreate()
Analytics.init(this) // network, disk
ImageLoader.preload(this) // heavy
Database.warmUp(this) // disk I/O
}
}
// Each of these adds milliseconds before the user sees anything.Jetpack 应用启动库
应用启动库会用一个共享的内容提供者替代多个内容提供者(每个提供者都会耗费时间),并让您清晰地表达初始化顺序和依赖关系。
您需要为每个组件实现一个 Initializer;应用启动库会按照依赖顺序运行它们各一次。
class AnalyticsInitializer : Initializer<Analytics> {
override fun create(context: Context): Analytics {
return Analytics.init(context.applicationContext)
}
// Runs after Logger is ready
override fun dependencies() = listOf(LoggerInitializer::class.java)
}
// Registered via a single merged provider in the manifest,
// avoiding one ContentProvider per library.延迟初始化与后台初始化
比安排急切执行的工作更好的方法,是在启动时少做一些工作。有两种策略:
- 延迟初始化:使用 Kotlin 的
by lazy,在首次使用时创建重量级对象。 - 后台初始化:将非界面初始化移出主线程。
这样,第一帧就不会被用户暂时不需要的工作阻塞。
class MyApp : Application() {
// Built only when first accessed, not during onCreate
val imageLoader by lazy { ImageLoader.build(this) }
override fun onCreate() {
super.onCreate()
// Push non-critical setup off the main thread
CoroutineScope(Dispatchers.Default).launch {
Analytics.init(applicationContext)
}
}
}AOT 与 JIT:首次运行为何缓慢
默认情况下,Android 通过解释执行和即时(JIT)编译的组合方式运行应用的字节码。热点代码首次运行时会先被解释执行(速度较慢);只有之后,运行时才会将其编译为原生代码。
这正是冷启动和首次滚动感觉更慢的原因。基线配置文件会告诉设备在安装时通过预先(AOT)编译重要代码,从而解决这个问题。
什么是基线配置文件
基线配置文件是关键操作流程(启动、首次滚动)中执行过的类和方法列表。您将它随应用一起发布;安装时,设备会对这些方法进行 AOT 编译,因此它们从首次启动开始就能以原生速度运行。
Google 报告称,启动速度通常可提升 20%–40%,而且无需修改功能代码——只需提供配置文件即可。
// build.gradle.kts
plugins { id("androidx.baselineprofile") }
dependencies {
baselineProfile(project(":baselineprofile"))
}
// The generated profile ships as
// assets/dexopt/baseline.prof
// and is applied automatically at install.生成基线配置文件
您可以编写一个小型测试,在设备上执行关键路径来生成配置文件;工具会记录运行过的方法,并写入配置文件。然后提交该文件并重新构建应用。
下面是一个典型的生成器,它会捕获启动和滚动操作。
@RunWith(AndroidJUnit4::class)
class BaselineProfileGenerator {
@get:Rule val rule = BaselineProfileRule()
@Test
fun generate() = rule.collect(packageName = "com.example.app") {
pressHome()
startActivityAndWait()
// exercise the critical journey
device.findObject(By.res("feed")).fling(Direction.DOWN)
}
}
// Run the generateBaselineProfile Gradle task to produce the file.验证优化效果
始终通过基准测试确认改进效果,比较应用使用和不使用配置文件时的启动情况(CompilationMode.None 与使用配置文件的 Partial)。
如果不进行测量,就无法证明配置文件确实有所帮助;过时的配置文件甚至可能造成负面影响。每当热点路径发生重大变化时,都应重新生成配置文件。
@Test
fun startupWithProfile() = rule.measureRepeated(
packageName = "com.example.app",
metrics = listOf(StartupTimingMetric()),
iterations = 10,
startupMode = StartupMode.COLD,
compilationMode = CompilationMode.Partial() // uses the baseline profile
) {
pressHome()
startActivityAndWait()
}启动优化计划
将这些步骤整合为一套可重复执行的计划:
- 使用 Macrobenchmark 和
adb am start -W测量冷启动。 - 精简
Application.onCreate:使用by lazy延迟初始化,并将工作移出主线程。 - 使用应用启动库合并内容提供者并安排初始化顺序。
- 随应用发布基线配置文件,以便对关键路径进行 AOT 编译。
- 通过基准测试验证效果,并保持配置文件为最新。
最终结果是:快速响应的第一帧会让用户明显感受到应用的速度。
快速检查
您随应用发布了一个基线配置文件。它主要通过什么方式改善启动?
回顾:从第一帧开始就很快
您已经学会了如何优化启动这一最直观的性能指标:
- 优化冷启动;使用 Macrobenchmark 和
adb am start -W进行测量。 - 保持
Application.onCreate轻量:进行延迟初始化,并将非界面工作放到后台。 - 使用应用启动库合并内容提供者并安排初始化器的顺序。
- 发布基线配置文件,使热点代码在安装时完成 AOT 编译,从而在首次运行时达到原生速度。
- 始终通过基准测试验证效果,并保持配置文件为最新。
至此,性能优化与分析课程完成:现在您可以进行测量、控制重组、修复泄漏,并让应用快速启动。
用 AI 导师学习 Kotlin — 免费
在浏览器中编写并运行真实代码,获得全天候 AI 导师的即时帮助,并在网页或应用中继续学习。
- 课程
- 36
- 课程
- 152
常见问题解答
「启动与基线配置文件」课时是免费的吗?
是的 — 「启动与基线配置文件」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Android Academy 课程的其余内容,请升级到 CoddyKit PRO。 Android Academy 课程共包含 4 节课。
「启动与基线配置文件」这节课中我会学到什么?
加快冷启动速度 你通过在浏览器中直接运行的动手代码来练习 Android Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Android Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Android Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 4 节课,共 4 节。
「启动与基线配置文件」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Android Academy 课中编写并运行代码吗?
能。每节 Android Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。