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
    └─ 注册监听器

相关推荐
没有了遇见5 分钟前
Android 架构之网络框架多域名配置<三>
android
myloveasuka1 小时前
[Java]单列集合
android·java·开发语言
fundroid2 小时前
Room 3.0 完全解析:一次面向未来的现代化重构
android·数据库·database·kmp
漂洋过海来看你啊2 小时前
Jetpack Compose高效列表实战:状态管理与性能优化指南
android
张宏2362 小时前
android camera hal3-camera_module_t
android
hongtianzai3 小时前
Laravel9.X核心特性全解析
android·java·数据库
七夜zippoe3 小时前
Python 3.12+ 新特性深度解析:类型系统与性能革命
android·网络·python·类型系统·性能革命·3.12+
Kapaseker3 小时前
五分钟搞定 Compose 的打字机效果
android·kotlin
彭波3963 小时前
听歌软件下载!全网音乐随便听!手机电脑+电视端!音乐播放器推荐
android·智能手机·音频·开源软件·娱乐·软件需求
江澎涌3 小时前
鸿蒙动态导入实战
android·typescript·harmonyos