You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Koin Android-KMM嵌套作用域注入失败:找不到AppointmentsRepository定义

Koin依赖注入错误:找不到AppointmentsRepository定义的解决方法

问题描述

使用Koin进行依赖注入时触发错误:

No definition found for class:'com.flow.domain.repository.AppointmentsRepository'. Check your definitions!

期望AppointmentsRepository的生命周期与UserInfoContainer作用域绑定,但注入流程无法正常执行。

核心问题分析

  1. 作用域不匹配:AppointmentsRepository定义在UserInfoContainer的专属作用域中,但AppointmentsUseCase默认从全局作用域查找实例,导致找不到对应定义。
  2. Scope初始化不规范:UserInfoContainer中getOrCreateScope()未指定与配置中匹配的作用域标识,创建的作用域和定义的scope<UserInfoContainer>不关联。
  3. 空指针风险:构造AppointmentsRepositoryImplementation时直接使用user!!.clinicId,未处理用户未初始化的场景。

解决方案

1. 修正UserInfoContainer的Scope初始化逻辑

确保创建的作用域与Koin配置中定义的scope<UserInfoContainer>匹配,同时在用户变更时重建作用域:

class UserInfoContainer(private val encryptedLocalDatabase: EncryptedLocalDatabase) :
    KoinScopeComponent {
    override val scope: Scope 
        get() = getOrCreateScope(named<UserInfoContainer>(), this).value

    var user: User?
        get() = encryptedLocalDatabase.user
        set(it) {
            if (it != encryptedLocalDatabase.user) {
                encryptedLocalDatabase.user = it
                scope.close()
                // 用户变更后重建作用域,保证后续实例使用最新用户数据
                getOrCreateScope(named<UserInfoContainer>(), this)
            }
        }
}

2. 在AppointmentsUseCase中指定作用域注入

由于AppointmentsRepository属于UserInfoContainer的作用域,注入时必须明确指定作用域来源,以下两种方式二选一:

方式一:让UseCase关联UserInfoContainer的作用域
class AppointmentsUseCase : KoinComponent, KoinScopeComponent {
    // 绑定到UserInfoContainer的作用域
    override val scope: Scope get() = get<UserInfoContainer>().scope

    private val appointmentsRepository: AppointmentsRepository by inject(scope = { scope })

    suspend fun getAppointments(startDate: LocalDateTime, endDate: LocalDateTime): List<Appointment> =
        appointmentsRepository.getAppointments(startDate, endDate)
}
方式二:直接指定注入的作用域
class AppointmentsUseCase : KoinComponent {
    private val userInfoContainer = get<UserInfoContainer>()
    private val appointmentsRepository: AppointmentsRepository by inject(scope = { userInfoContainer.scope })

    suspend fun getAppointments(startDate: LocalDateTime, endDate: LocalDateTime): List<Appointment> =
        appointmentsRepository.getAppointments(startDate, endDate)
}

3. 优化Repository构造的安全性

添加非空校验,避免空指针异常:

single { UserInfoContainer(encryptedLocalDatabase = get()) }

scope<UserInfoContainer> {
    scoped<AppointmentsRepository> {
        val userInfoContainer = get<UserInfoContainer>()
        checkNotNull(userInfoContainer.user) { "User必须先初始化才能创建AppointmentsRepository" }
        AppointmentsRepositoryImplementation(
            apiService = get(),
            clinicId = userInfoContainer.user!!.clinicId
        )
    }
}

内容的提问来源于stack exchange,提问作者EliodeBeirut

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 21:01:05