Android Koin 注入入门教程

Android Koin 注入入门教程

适合人群

  • Android 新手 / 刚接触 DI
  • 从 Dagger/Hilt 转 Koin
  • 多模块项目 / 车机项目开发者

目标

  • 理解「为什么要用 Koin」
  • 掌握 80% 常用注入方式
  • 避免 80% 新手必踩坑

一、什么是依赖注入(Dependency Injection)

1.1 不用 DI 会怎样?

kotlin 复制代码
class MusicViewModel {

    private val repository = MusicRepository()
}

问题

  • 强依赖具体实现
  • 无法替换 / 无法测试
  • 多模块会产生循环依赖

1.2 用 DI 后

kotlin 复制代码
class MusicViewModel(
    private val repository: MusicRepository
)
  • ViewModel 只依赖接口
  • 具体实现由外部"注入"
  • 解耦、可测试、可扩展

二、为什么选择 Koin?

对比项 Koin Dagger / Hilt
学习成本 ⭐ 低
编译速度
写法 Kotlin DSL 注解 + 生成代码
多模块灵活性
车机项目 ⭐ 非常合适 偏重

一句话

Koin = Kotlin 工程师友好的 DI 框架


三、Koin 的三大核心概念

3.1 Module(模块)

告诉 Koin:如何创建对象

kotlin 复制代码
val appModule = module {
    single { MusicRepository() }
}

3.2 Component(使用注入的地方)

kotlin 复制代码
class MusicViewModel(
    private val repository: MusicRepository
)

3.3 Koin 容器

在 Application 中启动

kotlin 复制代码
class MainApplication : Application() {

    override fun onCreate() {
        super.onCreate()

        startKoin {
            androidContext(this@MainApplication)
            modules(appModule)
        }
    }
}

四、最常用的注入方式(重点)

4.1 single ------ 单例(最常用)

kotlin 复制代码
single { MusicRepository() }
  • 整个 App 只有一个实例
  • 适合 Repository / Manager / Listener

4.2 factory ------ 每次新建

kotlin 复制代码
factory { PlayerController() }
  • 每次 inject 都创建新对象
  • 不适合 Listener

4.3 singleOf ------ 推荐写法 ⭐

kotlin 复制代码
singleOf(::MusicRepository)

优势:

  • 自动解析构造函数参数
  • 写法简洁
  • 官方推荐

五、如何在 Android 中注入?

5.1 在 Activity / Fragment 中

kotlin 复制代码
class MainActivity : AppCompatActivity() {

    private val repository: MusicRepository by inject()
}

5.2 在 ViewModel 中(推荐)

kotlin 复制代码
class MusicViewModel(
    private val repository: MusicRepository
) : ViewModel()

Module 中:

kotlin 复制代码
viewModel {
    MusicViewModel(get())
}

5.3 在普通类中(KoinComponent)

kotlin 复制代码
class PlayerManager : KoinComponent {

    private val repository: MusicRepository by inject()
}

六、接口 + 实现的标准写法

kotlin 复制代码
interface MusicRepository

class MusicRepositoryImpl : MusicRepository

Koin 配置:

kotlin 复制代码
single<MusicRepository> {
    MusicRepositoryImpl()
}

注入使用:

kotlin 复制代码
private val repository: MusicRepository by inject()

七、Android 多模块项目中的 Koin

7.1 模块拆分示例

复制代码
app
├── feature-localmusic
├── data
├── domain
└── base

每个模块都有自己的 Koin module:

kotlin 复制代码
val dataModule = module { ... }
val domainModule = module { ... }

在 Application 中统一加载:

kotlin 复制代码
startKoin {
    modules(
        appModule,
        dataModule,
        domainModule
    )
}

八、新手必踩的 5 个坑(必看)

❌ 1️⃣ 忘了加模块

kotlin 复制代码
modules(appModule) // 少了 dataModule

👉 直接导致 NoDefinitionFoundException


❌ 2️⃣ Listener 用了 factory

kotlin 复制代码
factory { PlayerStatusListener() } // 错

👉 会被重复注册

✅ 应使用:

kotlin 复制代码
single { PlayerStatusListener() }

❌ 3️⃣ single { MyClass } 少了括号

kotlin 复制代码
single { MyClass } // 错

必须:

kotlin 复制代码
single { MyClass() }

❌ 4️⃣ Startup 顺序错误

  • inject 发生在 startKoin 之前
  • 常见于 androidx.startup

👉 直接崩溃


❌ 5️⃣ 多进程没考虑

  • 车机项目常见
  • 每个进程都会启动 Koin

👉 单例 ≠ 全局唯一


九、一个完整可运行示例

AppModule.kt

kotlin 复制代码
val appModule = module {
    singleOf(::MusicRepository)
    viewModel { MusicViewModel(get()) }
}

Application.kt

kotlin 复制代码
class MainApplication : Application() {

    override fun onCreate() {
        super.onCreate()

        startKoin {
            androidContext(this@MainApplication)
            modules(appModule)
        }
    }
}

使用

kotlin 复制代码
class MusicFragment : Fragment() {

    private val viewModel: MusicViewModel by viewModel()
}

十、总结(记住这 3 句话)

1️⃣ Koin 不是魔法,只是对象工厂

2️⃣ single / factory 决定的是生命周期

3️⃣ Listener / Manager 一定要 single


相关推荐
阿巴斯甜5 小时前
Android 报错:Zip file '/Users/lyy/develop/repoAndroidLapp/l-app-android-ble/app/bu
android
Kapaseker6 小时前
实战 Compose 中的 IntrinsicSize
android·kotlin
xq95277 小时前
Andorid Google 登录接入文档
android
黄林晴8 小时前
告别 Modifier 地狱,Compose 样式系统要变天了
android·android jetpack
冬奇Lab21 小时前
Android触摸事件分发、手势识别与输入优化实战
android·源码阅读
城东米粉儿1 天前
Android MediaPlayer 笔记
android
Jony_1 天前
Android 启动优化方案
android
阿巴斯甜1 天前
Android studio 报错:Cause: error=86, Bad CPU type in executable
android
张小潇1 天前
AOSP15 Input专题InputReader源码分析
android
_小马快跑_1 天前
Kotlin | 协程调度器选择:何时用CoroutineScope配置,何时用launch指定?
android