在 Android 开发中,依赖注入(DI)是一种重要的设计模式,它能帮助我们降低代码耦合度、提高可测试性和可维护性。目前主流的 DI 框架中,Koin 以其轻量、简洁的特性逐渐成为许多开发者的首选。Koin 的核心设计理念是 "基于 Kotlin DSL 的运行时依赖解析",区别于 Hilt(基于 Dagger2 的编译期代码生成),它无需注解处理器(KAPT/KSP),完全通过 Kotlin 语法特性实现依赖的声明与注入,整体架构轻量且透明。
为什么选择 Koin?
Koin 作为一款基于 Kotlin 的依赖注入框架,相比其他框架具有多项显著优势:
- 简单且对开发人员友好:Koin 拥有干净的 DSL 语法,无需处理复杂的注解和代码生成,零编译时开销,最少的配置设置让开发者可以专注于业务逻辑实现。
 - 极致轻量:无论是小型项目还是复杂项目,Koin 都能轻松扩展以满足需求,不会给应用带来过多的体积负担。
 - 安全性保障:Koin 在运行时会进行依赖对象合法性检查,同时其 IDE 插件也即将发布,将进一步提升开发体验,弥补在 IDE 导航方面的短板。
 - 跨平台支持:作为纯 Kotlin 实现的框架,Koin 能够无缝管理 iOS、Android、桌面和 Web 等多平台的依赖项,是 Kotlin Multiplatform 开发的理想选择。
 - Jetpack Compose 友好:Koin 与 Jetpack Compose 集成极为轻松,完美支持 ViewModel 等界面组件的依赖注入,为未来迁移到 Compose Multiplatform 跨平台开发铺平道路。
 
Koin vs Hilt:核心差异
与 Google 官方推荐的 Hilt 框架相比,Koin 的优势主要体现在:
- 学习曲线:Koin 无需学习复杂的注解体系,通过简单直观的 DSL 即可完成依赖配置
 - 跨平台能力:Hilt 基于 Java 的 Dagger2,对 Kotlin Multiplatform 支持有限,而 Koin 天生支持多平台
 - 灵活性:Koin 无需代码生成,修改依赖配置后无需等待编译,开发效率更高
 - 轻量性:Koin 体积更小,对应用包体大小影响更小
 
性能方面,国外开发者对使用 Hilt 的官方示例 Now in Android 和使用 Koin 重写的版本进行的基准测试显示,两者性能差距极小,Koin 完全能满足日常开发需求。
核心组件
Koin 的架构由 5 个核心组件构成,各组件职责明确且协同工作:
| 组件 | 核心职责 | 
|---|---|
| KoinApplication | Koin 入口,负责初始化 Koin 容器、加载模块(Module)、管理全局配置(如日志、上下文) | 
| Module | 依赖声明载体,通过 DSL 定义 "如何创建实例"(如 single/factory/viewModel) | 
| Scope | 依赖生命周期容器,管理某一 "作用域" 内的实例(如 Activity 生命周期内的单例) | 
| InstanceFactory | 实例创建器,根据 Module 中声明的类型(single/factory/viewModel)创建并缓存实例 | 
| KoinComponent | 依赖消费者接口,实现该接口的类可通过 inject()/get() 方法获取依赖实例 | 
架构协同流程:
- 初始化:
KoinApplication加载Module,将依赖声明注册到内部容器; - 声明:
Module通过 DSL(如single { })定义实例创建规则,绑定到指定Scope; - 注入:
KoinComponent调用inject()/get(),触发InstanceFactory按规则创建 / 获取实例; - 生命周期管理:
Scope监听组件生命周期(如 Activity 销毁),自动清理该作用域内的实例。 
Koin 引入
Koin 采用 "核心包 + 扩展包" 的设计,开发者可根据项目场景(如 Android 原生、Compose、KMP)按需引入。以下是常用依赖包的详细说明:
| 依赖包坐标(artifactId) | 核心作用 | 适用场景 | 
|---|---|---|
koin-bom | 
用于集中管理所有 Koin 模块的版本,避免版本冲突 | 所有 | 
koin-core | 
Koin 核心功能:Module 定义、Scope 管理、依赖解析(平台无关) | 所有 Kotlin 项目(Android、KMP、后端) | 
koin-android-compat | 
Android 扩展:绑定 Application 上下文、支持 Activity/Fragment、ViewModel、SavedStateHandle注入 | Android 项目 | 
koin-androidx-compose | 
Compose 专用扩展:提供 koinInject()/koinViewModel() 等 Composable 方法(支持 Compose Multiplatform) | 
Compose 项目 | 
koin-androidx-startup | 
AndroidX Startup 自动初始化 | AndroidX Startup 1.1.0+ | 
koin-test | 
测试支持:提供 module.verify() 验证依赖图、Mock 实例注入 | 
单元测试(JVM/AndroidTest) | 
            
            
              gradle
              
              
            
          
          dependencies { 
    // 引入 BOM 管理所有 Koin 模块版本
    implementation platform("io.insert-koin:koin-bom:4.1.0")
    // 核心包 
    implementation "io.insert-koin:koin-core"
    // AndroidX 兼容(ViewModel) 
    implementation "io.insert-koin:koin-android-compat" 
    // Compose 集成 
    implementation "io.insert-koin:koin-androidx-compose" 
    // 测试支持 
    testImplementation "io.insert-koin:koin-test" 
}
        Koin 核心概念
模块(Module):依赖声明的载体
Module 是 Koin 中 "声明依赖" 的最小单元,通过 Kotlin DSL 定义 "如何创建实例",支持多模块拆分(如 networkModule、repositoryModule),便于模块化管理。
核心特性:
- 无侵入式 :无需修改被注入类(如无需加 
@Inject注解); - 支持分组 :通过 
listOf(module1, module2)合并多个模块; - 依赖传递 :模块内可通过 
get()自动解析依赖(如 ViewModel 依赖 Repository)。 
示例:
            
            
              kotlin
              
              
            
          
          // 网络模块:提供 Retrofit 实例
val networkModule = module {
    single {
        Retrofit.Builder()
            .baseUrl("https://api.example.com/")
            .addConverterFactory(GsonConverterFactory.create())
            .build()
    }
    // 依赖 Retrofit 创建 ApiService
    single { get<Retrofit>().create(ApiService::class.java) }
}
// 仓库模块:提供 Repository 实例
val repositoryModule = module {
    single { UserRepository(get<ApiService>()) }
}
// 合并模块
val appModules = listOf(networkModule, repositoryModule)
        实例类型:single、factory、viewModel 的区别
Koin 通过三种核心 DSL 函数定义实例的 "创建策略" 和 "生命周期",需根据业务场景选择:
| 函数 | 实例生命周期 | 适用场景 | 
|---|---|---|
single { } | 
全局单例(Koin 容器销毁前唯一) | 无状态服务(如 Retrofit、Database) | 
factory { } | 
每次获取新实例(无缓存) | 有状态对象(如 Activity 级别的工具类) | 
viewModel { } | 
绑定 ViewModel 生命周期(自动销毁) | Android ViewModel(与 Activity/Fragment 生命周期同步) | 
关键注意点:
viewModel { }内部依赖ViewModelProvider.Factory,无需手动实现工厂类;- 同一类型可通过 "限定符(Qualifier)" 区分多个实例(如不同环境的 Retrofit)。
 
限定符示例(多实例区分):
            
            
              kotlin
              
              
            
          
          val networkModule = module {
    // 生产环境 Retrofit
    single(qualifier = named("prod")) {
        Retrofit.Builder().baseUrl("https://prod.example.com/").build()
    }
    // 测试环境 Retrofit
    single(qualifier = named("test")) {
        Retrofit.Builder().baseUrl("https://test.example.com/").build()
    }
}
// 在 Module 中声明依赖时指定限定符
val repositoryModule = module {
    single {
        UserRepository(
            prodRetrofit = get(named("prod")),  // Koin 专用语法,无需注解
            testRetrofit = get(named("test"))
        )
    }
}
// UserRepository 类(纯 Kotlin 类,无任何注解)
class UserRepository(
    private val prodRetrofit: Retrofit,
    private val testRetrofit: Retrofit
)
        作用域(Scope):生命周期绑定的核心
Scope 是 Koin 中 "管理实例生命周期" 的关键概念,通过绑定 Android 组件或自定义生命周期,实现 "实例在指定范围内唯一",避免内存泄漏。
内置 Scope 组件
Koin 提供 3 个默认实现 AndroidScopeComponent 接口的组件,覆盖常见场景:
| 组件 | 生命周期特性 | 适用场景 | 
|---|---|---|
ScopeActivity | 
Activity 内单例,屏幕旋转时重新创建实例 | 不依赖旋转后状态保留的 Activity | 
RetainedScopeActivity | 
Activity 内单例,屏幕旋转时通过 ViewModel 保留实例 | 需保留状态的 Activity(如表单页面) | 
ScopeFragment | 
Fragment 内单例,Fragment 销毁时清理实例 | Fragment 场景 | 
自定义 Scope
若需更灵活的生命周期控制(如弹窗、组件化场景),可自定义 Scope:
            
            
              kotlin
              
              
            
          
          // 1. 定义 Scope ID
const val DIALOG_SCOPE_ID = "dialog_scope"
// 2. 在 Module 中声明 Scope 内的依赖
val dialogModule = module {
    scope(named(DIALOG_SCOPE_ID)) {
        scoped { DialogManager(get<Context>()) }  // scoped 表示 Scope 内单例
    }
}
// 3. 在代码中创建并使用 Scope
class CustomDialog(context: Context) : Dialog(context), KoinComponent {
    // 创建 Scope 并绑定到对话框生命周期
    private val dialogScope = getKoin().createScope(DIALOG_SCOPE_ID)
    // 从 Scope 中获取依赖
    private val dialogManager: DialogManager by dialogScope.inject()
    override fun dismiss() {
        super.dismiss()
        // 销毁 Scope,释放实例
        dialogScope.close()
    }
}
        依赖解析:inject () vs get ()
Koin 提供两种获取依赖的方式,核心区别在于 "是否懒加载":
| 方法 | 特性 | 适用场景 | 
|---|---|---|
by inject() | 
懒加载(Lazy 委托),首次使用时才解析依赖 | 依赖可能不被使用(如条件初始化) | 
get() | 
立即解析依赖,返回实例本身 | 依赖必须立即使用(如构造函数参数) | 
示例:
            
            
              kotlin
              
              
            
          
          class MainActivity : AppCompatActivity(), KoinComponent { // 注意需要实现KoinComponent接口
    // 懒加载:首次调用时解析
    private val userRepository: UserRepository by inject()
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // 立即解析:必须在 onCreate 中使用
        val apiService = get<ApiService>()
    }
}
        关键注意点:
- 在 
Activity/Fragment等需要使用 inject ()/get () 类中需实现KoinComponent接口; - 在 
ViewModel中通过构造函数注入时无需实现; - 在 
Compose中使用koinInject()时无需实现。 
上下文隔离(Context Isolation):多模块解耦
Koin 支持 "多 Koin 容器" 隔离,通过 KoinApplication 创建独立上下文,解决多模块(如 SDK、组件库)间的依赖冲突问题。
示例(SDK 模块隔离):
            
            
              kotlin
              
              
            
          
          // SDK 内部创建独立 Koin 容器
object SdkKoinContext {
    private val koinApp = koinApplication {
        modules(sdkInternalModule) // SDK 内部模块
    }
    val koin: Koin = koinApp.koin
}
// SDK 内部组件实现隔离的 KoinComponent
internal interface SdkKoinComponent : KoinComponent {
    override fun getKoin(): Koin = SdkKoinContext.koin
}
// SDK 内部使用隔离依赖
internal class SdkManager : SdkKoinComponent {
    private val sdkService: SdkService by inject()
}
        Koin 实战运用
初始化
简单项目,直接在 Application 类中初始化 Koin:
            
            
              kotlin
              
              
            
          
          class MyApp : Application() {
    override fun onCreate() {
        super.onCreate()
        // 启动 Koin
        startKoin {
            androidLogger(Level.DEBUG) // 开启日志(可选)
            androidContext(this@MyApp) // 绑定 Application 上下文
            modules(appModules) // 加载所有模块
        }
    }
}
        也可以通过 koin-androidx-startup 集成 AndroidX Startup 组件,实现 Koin 的自动初始化,减少对 Application 类的侵入,更符合组件化架构:
            
            
              kotlin
              
              
            
          
          class MyApp : Application(), KoinStartup { // 实现KoinStartup接口
    override fun onKoinStartup() = koinConfiguration {
        androidLogger(Level.DEBUG) // 开启日志(可选)
        androidContext(this@MyApp) // 绑定 Application 上下文
        modules(appModules) // 加载所有模块
    }
}
        注入 ViewModel:无工厂类简化开发
传统 ViewModel 传参需手动实现 ViewModelProvider.Factory,Koin 可通过 viewModel { } 简化:
无参 ViewModel
            
            
              kotlin
              
              
            
          
          // 1. 声明 ViewModel 模块
val viewModelModule = module {
    viewModel { UserViewModel() }
}
// 2. 在 Activity 中获取
class UserActivity : AppCompatActivity() {
    private val userViewModel: UserViewModel by viewModel()
}
        有参 ViewModel(依赖 Repository)
            
            
              kotlin
              
              
            
          
          // 1. 声明依赖链:ViewModel → Repository → ApiService
val viewModelModule = module {
    viewModel { UserViewModel(get()) } // get() 自动解析 UserRepository
}
val repositoryModule = module {
    single { UserRepository(get()) } // get() 自动解析 ApiService
}
// 2. ViewModel 实现(纯 Kotlin 类,无需继承特定父类)
class UserViewModel(private val repository: UserRepository) : ViewModel() {
    fun getUserInfo() = repository.getUserInfo()
}
        Compose 中使用 Koin:Composable 专用 API
Koin 为 Compose 提供 koinInject()(注入普通对象)和 koinViewModel()(注入 ViewModel),需引入 koin-androidx-compose 依赖:
注入普通对象
            
            
              kotlin
              
              
            
          
          @Composable
fun UserProfile() {
    // 注入 UserRepository(Composable 内专用)
    val userRepository: UserRepository = koinInject()
    LaunchedEffect(Unit) {
        val userInfo = userRepository.getUserInfo()
    }
}
        注入 ViewModel(带参数)
            
            
              kotlin
              
              
            
          
          // 1. 声明带参数的 ViewModel
val viewModelModule = module {
    viewModel { (userId: String) -> UserDetailViewModel(userId, get()) }
}
// 2. Compose 中传递参数
@Composable
fun UserDetailScreen(userId: String) {
    val viewModel: UserDetailViewModel = koinViewModel(
        parameters = { parametersOf(userId) } // 传递参数
    )
}
        多模块通信:接口解耦
Koin 可实现多模块(如 Base 模块与业务模块)间的接口通信,类似 ARouter 的跨模块调用:
示例(Base 模块定义接口,User 模块实现):
            
            
              kotlin
              
              
            
          
          // 1. Base 模块定义接口
interface IUserService {
    fun getUserToken(): Flow<String>
}
// 2. User 模块实现接口并声明依赖
class UserServiceImpl : IUserService {
    override fun getUserToken() = flow { emit("token_123") }
}
val userModule = module {
    single<IUserService> { UserServiceImpl() } // 绑定接口与实现
}
// 3. 其他模块(如 Order 模块)使用接口
class OrderRepository : KoinComponent {
    private val userService: IUserService by inject()
    fun getOrderList() = userService.getUserToken().map { token ->
        // 用 token 请求订单列表
    }
}
        测试支持:验证依赖与 Mock 注入
Koin 提供 koin-test 库,支持两种核心测试场景:
验证 Module 依赖图
通过 module.verify() 检查模块内依赖是否完整(避免运行时异常):
            
            
              kotlin
              
              
            
          
          class KoinModuleTest {
    @Test
    fun testModuleDependency() {
        // 验证所有模块的依赖关系
        appModules.verify()
    }
}
        Mock 依赖注入
使用 MockK/Mockito 替换真实依赖,便于单元测试:
            
            
              kotlin
              
              
            
          
          class UserViewModelTest : KoinTest {
    private val mockRepository = mockk<UserRepository>()
    @Before
    fun setup() {
        // 启动测试用 Koin,替换真实依赖为 Mock
        startKoin {
            modules(module {
                single { mockRepository }
                viewModel { UserViewModel(get()) }
            })
        }
    }
    @Test
    fun testGetUserInfo() {
        // 模拟 Repository 返回
        coEvery { mockRepository.getUserInfo() } returns "test_user"
        
        // 获取 ViewModel 并测试
        val viewModel: UserViewModel = get()
        viewModel.getUserInfo().test().assertValue("test_user")
    }
}
        架构设计
Koin 并非孤立存在,而是与现代 Android 架构(如 MVVM、Clean Architecture)深度契合的工具。合理的架构设计能最大化 Koin 的价值,减少依赖管理复杂度。
分层模块划分
一般简单应用采用分层模块划分,将依赖按"数据层-领域层-UI层"分离,每个层对应独立的 Koin 模块,通过接口实现层间解耦。
架构分层与模块对应关系
| 架构层 | 职责 | Koin 模块示例 | 核心依赖类型 | 
|---|---|---|---|
| 数据层 | 数据获取与存储(API/数据库) | networkModule、storageModule | 
single(Retrofit、Room) | 
| 领域层 | 业务逻辑与数据处理 | repositoryModule、useCaseModule | 
single(Repository、UseCase) | 
| UI层 | 界面展示与用户交互 | viewModelModule、uiModule | 
viewModel、factory | 
示例:分层模块设计
            
            
              kotlin
              
              
            
          
          // 1. 数据层:网络模块
val networkModule = module {
    single { Retrofit.Builder().baseUrl(BASE_URL).build() }
    single { get<Retrofit>().create(UserService::class.java) }
}
// 2. 数据层:本地存储模块
val storageModule = module {
    single { AppDatabase.getDatabase(get()) } // 依赖 Context
    single { get<AppDatabase>().userDao() }
}
// 3. 领域层:仓库模块(依赖数据层接口)
val repositoryModule = module {
    single { UserRepository(get<UserService>(), get<UserDao>()) }
}
// 4. 领域层:用例模块(依赖仓库)
val useCaseModule = module {
    factory { GetUserInfoUseCase(get()) } // 每次使用创建新实例
    factory { UpdateUserUseCase(get()) }
}
// 5. UI层:ViewModel模块(依赖用例)
val viewModelModule = module {
    viewModel { UserProfileViewModel(get<GetUserInfoUseCase>(), get<UpdateUserUseCase>()) }
}
// 合并所有模块
val appModules = listOf(
    networkModule,
    storageModule,
    repositoryModule,
    useCaseModule,
    viewModelModule
)
        模块化项目
大型项目通常按业务拆分模块(如 user、order、common),Koin 可通过模块组合实现跨模块依赖管理,避免模块间硬编码依赖。
关键原则:
- 公共模块暴露接口 :
common模块定义通用接口(如AnalyticsService),具体实现由业务模块提供; - 业务模块独立声明依赖 :
user模块仅声明自身需要的依赖,不关心其他模块实现; - 主模块负责组合 :
app模块汇总所有业务模块的 Koin 模块,完成最终组装。 
示例:模块化项目的模块组合
            
            
              kotlin
              
              
            
          
          // common 模块:定义接口
interface AnalyticsService {
    fun trackEvent(event: String)
}
// user 模块:声明依赖(依赖 common 接口)
val userModule = module {
    single { UserManager(get<AnalyticsService>()) } // 依赖接口,不依赖实现
}
// order 模块:声明依赖
val orderModule = module {
    single { OrderManager(get<AnalyticsService>()) }
}
// app 模块:提供接口实现并组合所有模块
val appModule = module {
    single<AnalyticsService> { FirebaseAnalyticsService() } // 实现 common 接口
}
// 主模块组合
val allModules = listOf(appModule, userModule, orderModule)
        循环依赖:检测、分析与解决方案
循环依赖(A 依赖 B,B 依赖 A)是 DI 中常见的问题,Koin 运行时会抛出 CyclicDependencyException。解决循环依赖的核心是打破依赖闭环,而非绕过异常。
循环依赖的常见场景与检测
典型场景:
- 双向依赖 :
ViewModel依赖Repository,Repository依赖ViewModel(错误设计); - 多层闭环 :
A → B → C → A的多层依赖链; - 隐式依赖:通过全局静态变量或单例间接形成的依赖闭环。
 
检测方法:
- 
运行时异常 :Koin 会直接抛出
CyclicDependencyException,堆栈信息会显示依赖链; - 
静态分析 :使用
module.verify()在测试中提前检测: 
            
            
              kotlin
              
              
            
          
          @Test
fun testNoCyclicDependencies() {
    // 验证模块是否存在循环依赖
    appModules.verify() 
}
        解决方案:从设计层面打破闭环
方案 1:通过接口分离依赖
将依赖双方的交互抽象为接口,使一方依赖接口而非具体实现,打破直接依赖。
            
            
              kotlin
              
              
            
          
          // 问题场景:UserViewModel 依赖 UserRepository,UserRepository 依赖 UserViewModel
// 解决方案:抽象接口
// 1. 定义接口(由 ViewModel 实现)
interface UserStateListener {
    fun onUserUpdated(user: User)
}
// 2. ViewModel 实现接口
class UserViewModel(
    private val repository: UserRepository
) : ViewModel(), UserStateListener {
    init {
        repository.setListener(this) // 传递接口实例,而非自身
    }
    override fun onUserUpdated(user: User) {
        // 处理更新
    }
}
// 3. Repository 依赖接口,而非 ViewModel
class UserRepository(
    private val api: UserService
) {
    private var listener: UserStateListener? = null
    fun setListener(listener: UserStateListener) {
        this.listener = listener
    }
    fun updateUser(user: User) {
        // 业务逻辑
        listener?.onUserUpdated(user) // 调用接口方法
    }
}
// 4. Koin 模块声明
val module = module {
    viewModel { UserViewModel(get()) }
    single { UserRepository(get()) }
}
        方案 2:使用懒加载(by inject())延迟依赖解析
Koin 的 by inject() 是懒加载委托,可延迟依赖实例化,避免初始化时的闭环(仅适用于 "依赖双方非初始化阶段互相调用" 的场景。若初始化时就调用对方方法,仍会触发循环依赖异常)。
            
            
              kotlin
              
              
            
          
          // 适用场景:双方依赖但非初始化阶段立即使用
class A : KoinComponent {
    // 懒加载依赖 B
    private val b: B by inject()
    fun doSomething() {
        b.action() // 首次使用时才解析 B
    }
}
class B : KoinComponent {
    // 懒加载依赖 A
    private val a: A by inject()
    fun action() {
        a.react() // 首次使用时才解析 A
    }
}
val module = module {
    single { A() }
    single { B() }
}
        方案 3:重构业务逻辑,移除不必要依赖
循环依赖往往是业务逻辑设计不合理的信号,可通过职责分离重构代码。
例如:Repository 不应依赖 ViewModel,可将共享逻辑提取到独立的 UseCase 或 Manager 中:
            
            
              kotlin
              
              
            
          
          // 重构前:Repository 依赖 ViewModel
// 重构后:引入中间层 UserManager
class UserManager {
    // 存放原 Repository 和 ViewModel 的共享逻辑
    private val userFlow = MutableStateFlow<User?>(null)
    fun updateUser(user: User) {
        userFlow.value = user
    }
    fun getUserFlow() = userFlow.asStateFlow()
}
// Repository 依赖 UserManager
class UserRepository(
    private val api: UserService,
    private val manager: UserManager
) {
    fun fetchUser() {
        // 业务逻辑
        manager.updateUser(user) // 通知更新
    }
}
// ViewModel 依赖 UserManager
class UserViewModel(
    private val manager: UserManager
) : ViewModel() {
    val user by manager.getUserFlow().collectAsState()
}
// Koin 模块
val module = module {
    single { UserManager() }
    single { UserRepository(get(), get()) }
    viewModel { UserViewModel(get()) }
}
        结合工具与库
Koin 可与众多 Android 主流库无缝集成:
网络与数据存储
Retrofit + Koin
网络请求是依赖注入的典型场景,Koin 可集中管理 Retrofit 实例和 API 服务:
            
            
              kotlin
              
              
            
          
          val networkModule = module {
    single {
        OkHttpClient.Builder()
            .addInterceptor(HttpLoggingInterceptor())
            .build()
    }
    
    single {
        Retrofit.Builder()
            .baseUrl("https://api.example.com/")
            .client(get())
            .addConverterFactory(GsonConverterFactory.create())
            .build()
    }
    
    single { get<Retrofit>().create(UserApi::class.java) }
    single { get<Retrofit>().create(OrderApi::class.java) }
}
        Room + Koin
数据库实例适合作为全局单例,通过 Koin 注入可避免重复创建:
            
            
              kotlin
              
              
            
          
          val databaseModule = module {
    single {
        Room.databaseBuilder(
            get(), // 从 Koin 获取 Context
            AppDatabase::class.java,
            "app_db"
        ).build()
    }
    
    single { get<AppDatabase>().userDao() }
    single { get<AppDatabase>().orderDao() }
}
        图片加载与缓存
Coil + Koin
Coil 是 Kotlin 编写的图片加载库,与 Koin 结合可自定义全局配置:
            
            
              kotlin
              
              
            
          
          val imageModule = module {
    single {
        ImageLoader.Builder(get()) // 依赖 Context
            .crossfade(true)
            .okHttpClient {
                OkHttpClient.Builder()
                    .cache(CoilUtils.createDefaultCache(get()))
                    .build()
            }
            .build()
    }
}
// 在 Compose 中使用
@Composable
fun UserAvatar(url: String) {
    val imageLoader: ImageLoader by koinInject()
    AsyncImage(
        model = url,
        contentDescription = "User avatar",
        imageLoader = imageLoader
    )
}
        状态管理与事件总线
Flow + Koin
Kotlin Flow 作为现代状态管理方案,与 Koin 结合可实现数据流的注入:
            
            
              kotlin
              
              
            
          
          // 用户状态管理器:负责持有和更新用户状态 Flow
class UserStateManager {
    // 1. 私有可变 Flow(MutableStateFlow):内部可修改
    // 初始值设为"空用户",确保页面有默认数据可展示
    private val _userState = MutableStateFlow<User>(EMPTY_USER)
    
    // 2. 公开只读 Flow(StateFlow):外部只能观察,不能修改
    // 用 asStateFlow() 转换,避免外部强制类型转换后修改数据
    val userState: StateFlow<User> = _userState.asStateFlow()
    // 3. 公开方法:更新用户状态(外部只能通过此方法修改数据)
    fun updateUser(newUser: User) {
        // 切换到主线程更新(StateFlow 推荐在主线程发射数据,避免线程安全问题)
        CoroutineScope(Dispatchers.Main).launch {
            _userState.value = newUser
        }
    }
}
// 用户状态相关的 Koin 模块
val userStateModule = module {
    // 注册 UserStateManager 为全局单例(single)
    // 原因:整个 APP 只需要一个用户状态管理器,确保所有页面观察的是同一数据流
    single { UserStateManager() }
}
// 合并到 APP 总模块(与其他模块一起初始化)
val appModules = listOf(
    userStateModule,  // 加入用户状态模块
    networkModule,    // 其他模块(如网络、数据库)
    viewModelModule   // 其他模块(如 ViewModel)
)
/ 个人中心 ViewModel
class ProfileViewModel(
    // 1. 通过构造函数注入 UserStateManager(Koin 自动提供实例)
    private val userStateManager: UserStateManager,
    // 2. 同时注入网络依赖(示例:登录请求需要的 API 服务)
    private val userApi: UserApi
) : ViewModel() {
    // 3. 暴露用户状态 Flow 给 UI(直接转发管理器的只读 Flow)
    // UI 层只需观察这个 Flow,无需关心数据来源
    val userState: StateFlow<User> = userStateManager.userState
    // 4. 业务逻辑:登录(成功后更新用户状态)
    fun login(username: String, password: String) {
        viewModelScope.launch {
            try {
                // 发起网络请求(示例:调用登录接口)
                val loginResponse = userApi.login(username, password)
                if (loginResponse.isSuccess) {
                    val userInfo = loginResponse.data
                    // 登录成功:更新用户状态(触发所有观察此 Flow 的 UI 刷新)
                    userStateManager.updateUser(userInfo)
                } else {
                    // 登录失败:重置为未登录状态
                    userStateManager.updateUser(EMPTY_USER)
                }
            } catch (e: Exception) {
                // 网络异常:重置状态
                userStateManager.updateUser(EMPTY_USER)
            }
        }
    }
}
        EventBus(如 TinyBus) + Koin
轻量级事件总线可通过 Koin 注入,避免全局静态引用:
            
            
              kotlin
              
              
            
          
          val eventModule = module {
    single { TinyBus(get<Application>()) } // 依赖 Application 上下文
}
// 在 ViewModel 中使用
class UserViewModel(
    private val eventBus: TinyBus
) : ViewModel() {
    init {
        eventBus.register(this)
    }
    
    @Subscribe
    fun onUserEvent(event: UserEvent) {
        // 处理事件
    }
    
    override fun onCleared() {
        eventBus.unregister(this)
        super.onCleared()
    }
}