1.1 按需加载模块基本概念
按需加载(On-Demand Delivery)是 Android 为解决安装包膨胀而推出的核心策略,它允许应用在运行时动态下载之前未包含在基础 APK 中的功能模块。本章将系统梳理支撑这一能力的三项关键技术:Android App Bundle、Dynamic Feature 以及 SplitInstall 库,并辨析按需加载与延迟加载的本质区别。
1.1.1 Android App Bundle
Android App Bundle(AAB)是 Google 推荐的官方发布格式,它将应用拆分为多个分发单元(Split),而不是单个巨型 APK。
- 基础模块(Base Module):包含核心代码、资源和清单,是运行时必须的部分。
- 功能模块(Dynamic Feature Module):按需分发的独立模块,仅在用户触发时才下载。
- 配置 APK(Configuration APKs):针对屏幕密度、CPU 架构等自动生成的优化包。
💡 实践要点:Google Play 商店在下载时仅向设备推送最匹配的配置 APK + 基础模块,从而平均减少约 15%–20% 的下载量。
1.1.2 Dynamic Feature 模块
Dynamic Feature 是 AAB 生态中的按需分发单元。开发者可以在 build.gradle 中声明该模块的安装时机:
| 安装时机 | 行为说明 |
|---|---|
install-time | 随基础模块一起安装,同传统 APK 行为 |
on-demand | 用户主动触发时加载,这是按需加载的典型模式 |
conditional | 仅在满足特定条件(如系统版本、地区)时安装 |
关键配置示例(位于 Dynamic Feature 模块的
build.gradle):
android {
dynamicFeatures = [":cameralens", ":ar_module"]
defaultConfig {
// 使用 split 分发
splits {
abi { enable true; reset(); include "x86", "arm64-v8a" }
}
}
}
dependencies {
implementation "com.google.android.play:core:1.10.3"
// 注意:play-core 必须添加到基础模块和每个 DF 模块
}
1.1.3 SplitInstall 库
SplitInstall 是 Google Play Core 库提供的客户端 API,负责在 Android 设备上下载、安装和管理来自 Google Play 的动态功能模块。核心能力包括:
- 请求安装:通过
SplitInstallManager发起按需下载。 - 进度监听:支持回调
onInstallStateUpdate获取下载/安装状态。 - 模块卸载:通过
deferredUninstall()清理不再需要的模块。 - 错误处理:包括网络失败、存储不足、模块未发布等场景。
⚠️ SplitInstall 仅在通过 Google Play 分发的 AAB 包上生效。侧载或非 Play 商店安装无法使用该 API。
1.1.4 按需加载 vs 延迟加载
两种策略虽然都涉及“晚加载”,但机制完全不同。下表从多个维度进行对比:
| 维度 | 按需加载 | 延迟加载 |
|---|---|---|
| 触发时机 | 用户显式操作(点击按钮、进入页面) | 应用启动或空闲时段的后台预加载 |
| 是否依赖 Play 商店 | 是,通过 SplitInstall API 请求Google Play | 否,模块已存在于基础 APK 中 |
| 网络需求 | 需要网络下载模块 | 不需要,从本地存储加载 |
| 安装包体积影响 | 大幅减少首次安装体积 | 不减少,模块始终在包内 |
| 用户体验 | 首次使用需等待下载完成 | 几乎零延迟,但占用预加载资源 |
| 典型场景 | 付费功能、AR 模块、语音包 | 首页数据预取、子页面预初始化 |
在实际项目中,两者通常配合使用:按需加载解决“不该提前打包”的问题,延迟加载优化“已经打包但暂不需要”的资源。
代码示意:使用 SplitInstallManager 发起按需下载
// 早期初始化(onCreate 中获取 Manager)
SplitInstallManager manager =
SplitInstallManagerFactory.create(context);
// 构建要安装的模块名称列表
SplitInstallRequest request =
SplitInstallRequest.newBuilder()
.addModule("cameralens")
.addModule("filter_pack")
.build();
// 异步发起下载
manager.startInstall(request)
.addOnSuccessListener(sessionId -> Log.i("DF", "安装启动: " + sessionId))
.addOnFailureListener(e -> {
// 处理常见错误:网络、存储、模块未定义等
if (e instanceof SplitInstallException) {
int errorCode = ((SplitInstallException) e).getErrorCode();
// 根据 errorCode 做降级处理
}
});
以上代码展示了按需加载的核心调用模式:通过 Play Core 库提供的 API,开发者可以精确控制模块的下载时机,而无需在基础 APK 中打包这些功能。