android Initializer 启动入门


一、整体大图

这是一个「去 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() 之前,必须先执行:

  1. LogInitializer
  2. KoinInitializer

为什么一定要依赖 KoinInitializer?

因为你这里用了:

kotlin 复制代码
by inject()

如果 Koin 没启动

  • ❌ 注入直接 crash
  • NoBeanDefFoundException

五、三者之间的关系(总结图)

复制代码
AndroidManifest.xml
        ↓
AndroidX Startup 扫描
        ↓
KoinInitializer
    ├─ startKoin()
    └─ 建立 DI 容器
        ↓
PlayxxManagerInitializer
    ├─ 通过 Koin 注入 Listener
    ├─ 初始化 Repository
    ├─ 初始化 PlayControlManager
    └─ 注册监听器

相关推荐
·云扬·10 小时前
系统与MySQL核心监控指标及操作指南
android·数据库·mysql
冬奇Lab10 小时前
【Kotlin系列01】Kotlin快速入门:环境搭建与Hello World
android·kotlin·android studio
君莫啸ོ11 小时前
Android 自定义View-圆圈扩散动画
android
stevenzqzq11 小时前
android启动和注入理解1
android
qq_7174100111 小时前
修改飞行模式
android
Larry_Yanan11 小时前
Qt安卓开发(一)Qt6.10环境配置
android·开发语言·c++·qt·学习·ui
冬奇Lab11 小时前
稳定性性能系列之十——卡顿问题分析:从掉帧到流畅体验
android·性能优化
stevenzqzq12 小时前
android启动初始化和注入理解2
android