Koin 依赖注入深度解析:Single、Factory 与 Scoped 到底怎么选?

在 Kotlin 的世界里,Koin 以其"无反射、极简 DSL"的特性让开发者倍感幸福。但要用好 Koin,理解其三大核心定义类型:singlefactoryscoped 是必修课。


一、 single:全局唯一的单例 (Singleton)

single 是 Koin 中最常用的定义方式。

  • 本质 :在整个 Koin 容器的生命周期内(通常是应用的生命周期),该定义的实例只会被创建一次。后续所有的注入请求都会返回同一个对象。

  • 生命周期:与应用进程共存亡。

  • 适用场景

    • Repository 层:数据仓库通常不需要重复创建。
    • 网络模块:如 Retrofit 实例、OkHttpClient。
    • 本地数据库:如 Room 数据库实例。

代码示例:

Kotlin

java 复制代码
val appModule = module {
    // 整个应用运行期间,只有一个 UserRepository 实例
    single { UserRepository(get()) }
}

二、 factory:按需创建的工厂 (Factory)

single 相反,factory 每次都会给你提供一个"全新的"对象。

  • 本质 :每次进行注入(通过 inject()get())时,Koin 都会执行一次代码块,创建一个新的实例

  • 生命周期:Koin 不负责保存这个实例,它的生命周期由调用者决定(例如被赋值给某个局部变量)。

  • 适用场景

    • 临时的 UI 逻辑类:不需要持久化状态的小工具。
    • 具有状态的对象:你不希望不同页面共享同一个状态的对象。

代码示例:

Kotlin

java 复制代码
val appModule = module {
    // 每次注入都会创建一个新的 Presenter 实例
    factory { UserPresenter(get()) }
}

三、 scoped:受控的作用域 (Scoped)

这是 Koin 中最强大但也最容易被误解的部分。它介于 singlefactory 之间。

  • 本质:实例在一个特定的**作用域(Scope)**内是唯一的。当作用域开启时创建,当作用域关闭(如 Activity 销毁)时,该实例也会随之销毁。

  • 生命周期:绑定到特定的组件生命周期。

  • 适用场景

    • 分步表单/向导界面:在 3 个 Fragment 之间共享数据,但一旦退出该流程,数据应立即清除。
    • Activity 专有数据:只在某个特定页面及其内部子组件中共享。

代码示例:

Kotlin

java 复制代码
val appModule = module {
    // 定义一个作用域
    scope<MyActivity> {
        // 在 MyActivity 的生命周期内,该实例是单例
        scoped { UserSession() }
    }
}

四、 核心差异对比表

特性 single factory scoped
实例数量 全局只有一个 每次请求都有一个新实例 作用域内唯一
内存占用 持续占用,直到应用关闭 瞬时占用,随用随关 随作用域生命周期释放
实例共享 全局共享 不共享 仅在当前作用域内共享
推荐用途 数据库、API 客户端、Repo 工具类、瞬时数据处理 页面私有逻辑、分步任务流

五、 避坑与最佳实践

  1. 关于 ViewModel :在 Android 中,Koin 提供了专用的 viewModel { ... } 关键字。它的行为类似于 factory,但由系统的 ViewModelProvider 托管,确保在配置更改(如旋转屏幕)时实例不被销毁。
  2. 避免滥用 single :虽然 single 很省事,但如果把太多具有状态的逻辑类定义为单例,会导致内存积压,甚至出现"退出登录后数据未清理"的诡异 Bug。
  3. Scoped 的自动释放 :在 Android 中使用 scoped 时,建议配合 ActivityScopeFragmentScope 的扩展,这样 Koin 能在组件 onDestroy() 时自动帮你回收资源,避免内存泄漏。
相关推荐
AFinalStone2 小时前
Android 7系统异常问题排查(四)Framework层(上)—System Server Watchdog
android·系统异常
宝杰X74 小时前
Android Room3 多平台数据库
android·数据库
huibin1478523696 小时前
热缓解学习记录
android·学习
我命由我123459 小时前
匈牙利命名法
java·服务器·后端·学习·java-ee·kotlin·学习方法
小田的博客9 小时前
SAP MM 供应商银行主数据更新报错!message R1228!
android·java·服务器
一笑的小酒馆10 小时前
Android智能猫砂盆视频加载慢卡顿问题分析
android
只会cv的小前端12 小时前
七巧低代码服务端脚本使用方法
android·低代码·rxjava
12 小时前
Android 自定义 View 实战:从零打造工业级全向摇杆控件(OmniJoystickView)
android·kotlin·自定义view·摇杆控件
雨白12 小时前
深入理解 Kotlin 协程 (十一):以逸待劳,探秘 select 多路复用与并发安全策略
android·kotlin
刘名喜14 小时前
第22篇-数据库迁移-Liquibase
kotlin·springboot