一、整体大图
这是一个「去 Application 化」的初始化设计
- 不在
Application.onCreate()里手写初始化逻辑 - 改用
androidx.startup.Initializer - 通过 Manifest 声明 + 依赖关系 自动完成初始化顺序
初始化顺序(非常关键):
Application 启动
↓
AndroidX Startup 扫描 Manifest
↓
KoinInitializer.create() ← 初始化 DI 容器
↓
PlayxxxManagerInitializer.create() ← 依赖 Koin,可注入对象
二、第一部分:AndroidManifest.xml(入口)
xml
<meta-data
android:name="com.xx.a"
android:value="androidx.startup" />
<meta-data
android:name="com.xxx.b"
android:value="androidx.startup" />
1️⃣ 这是干嘛的?
这是 AndroidX Startup 的注册方式:
- 每一个
<meta-data android:value="androidx.startup"/> - 就表示:这是一个 Initializer,需要在 App 启动时自动执行
不需要你在任何地方手动调用
2️⃣ Startup 在什么时候执行?
ContentProvider阶段(比 Application.onCreate 还早)- 系统启动 App → Startup Provider 被加载 → 执行 Initializer
⚠️ 所以这些代码 都发生在 App 冷启动最早期
三、第二部分:KoinInitializer(DI 容器初始化)
kotlin
class KoinInitializer : Initializer<Boolean> {
1️⃣ 它的职责(非常单一)
只做一件事:启动 Koin 容器
kotlin
startKoin {
androidLogger(...)
androidContext(context)
modules(koinModules)
}
这一步完成后:
- 全局 Koin 容器建立
- 所有
single / factory / viewModel都可被注入 by inject()才能正常工作
2️⃣ 为什么要用 Initializer 而不是 Application?
优点非常明显:
| 方式 | 问题 |
|---|---|
| Application.onCreate | 容易膨胀、耦合严重 |
| AndroidX Startup | 模块化、自动排序、可独立测试 |
尤其在 多模块 / 车机项目 中,这是业界推荐写法
3️⃣ dependencies() 为什么返回空?
kotlin
override fun dependencies() = mutableListOf<Class<out Initializer<*>>>()
表示:
- 它不依赖任何其他初始化器
- 它是"最底层基础设施"
👉 这也是为什么 其他 Initializer 都要依赖它
四、第三部分:PlayControlManagerInitializer(业务初始化)
kotlin
class PlayControlManagerInitializer :
Initializer<PlayControlManager>,
KoinComponent
这是整套设计的 核心亮点
四-1:为什么要实现 KoinComponent?
kotlin
private val playerStatusSavedListener: PlayerStatusSavedListener by inject()
原理解释:
Initializer本身 不是 Android 组件- 没有 Context / Lifecycle / ViewModelScope
- 无法自动注入
👉 实现 KoinComponent 后:
- 当前类 可以访问 Koin 容器
by inject()才能生效
⚠️ 前提:
Koin 容器必须已经
startKoin()完成
四-2:create() 里做了什么?
kotlin
override fun create(context: Context): PlayControlManager {
初始化顺序拆解:
① 初始化 Repository 工厂
kotlin
RepositoryFactory.instance.init(context)
- 建立数据访问层
- 为播放器提供数据支持
② 初始化播放控制单例
kotlin
PlayxxManager.instance.init(
context,
RepositoryFactory.instance,
RepoConstant.SUPPLIER_LOCAL_MUSIC
)
- 标准 饿汉 / 单例初始化
- 绑定数据源 & Context
③ 设置默认播放模式
kotlin
PlayxxManager.instance.setDefaultPlayMode(PlayMode.LoopPlay)
④ 注入 & 注册 Listener(关键)
kotlin
PlayxxManager.instance.addPlayerStatusListener(playerxxListener)
⚠️ 这里的 playerStatusSavedListener:
- 来自 Koin 注入
- 依赖 KoinInitializer 已执行
四-3:dependencies() 的真正意义(最关键)
kotlin
override fun dependencies() =
mutableListOf(LogInitializer::class.java, KoinInitializer::class.java)
这是整个设计的 "顺序控制器"
含义是:
在执行
PlayxxManagerInitializer.create()之前,必须先执行:
LogInitializerKoinInitializer
为什么一定要依赖 KoinInitializer?
因为你这里用了:
kotlin
by inject()
如果 Koin 没启动:
- ❌ 注入直接 crash
- ❌
NoBeanDefFoundException
五、三者之间的关系(总结图)
AndroidManifest.xml
↓
AndroidX Startup 扫描
↓
KoinInitializer
├─ startKoin()
└─ 建立 DI 容器
↓
PlayxxManagerInitializer
├─ 通过 Koin 注入 Listener
├─ 初始化 Repository
├─ 初始化 PlayControlManager
└─ 注册监听器