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

Dagger2跨模块注入:替换Interface实现的方案咨询

解决方案:Dagger2跨模块注入Logging接口实现

方案一:依赖反转+组件继承(推荐)

这是最符合Dagger设计理念的方式,无需dummy实现或Optional,让core模块独立编译的同时,app模块提供真实实现。

步骤1:Core模块定义接口与核心组件

在core模块中只声明Logging接口、核心业务逻辑,以及一个抽象的CoreComponent(不绑定具体实现):

// core/src/main/java/com/example/core/Logging.kt
interface Logging {
    fun log(message: String)
    fun logError(throwable: Throwable)
}

// core/src/main/java/com/example/core/CoreComponent.kt
@Component(modules = [CoreModule::class])
interface CoreComponent {
    // 暴露Logging实例,供下游组件使用
    fun logging(): Logging
    // 暴露核心业务逻辑类
    fun businessLogic(): BusinessLogic
}

// core/src/main/java/com/example/core/CoreModule.kt
@Module
class CoreModule {
    @Provides
    fun provideBusinessLogic(logging: Logging): BusinessLogic {
        return BusinessLogic(logging)
    }
}

// core/src/main/java/com/example/core/BusinessLogic.kt
class BusinessLogic(private val logging: Logging) {
    fun execute() {
        logging.log("Core business logic executed")
    }
}

core模块编译时只依赖接口和抽象组件,不需要具体实现,完全可以独立构建。

步骤2:App模块实现组件与真实Logging

在app模块中创建继承自CoreComponent的AppComponent,并绑定真实的Logging实现:

// app/src/main/java/com/example/app/RemoteLogging.kt
class RemoteLogging : Logging {
    override fun log(message: String) {
        // 实现向服务器发送日志的逻辑
    }

    override fun logError(throwable: Throwable) {
        // 实现向服务器发送错误信息的逻辑
    }
}

// app/src/main/java/com/example/app/AppModule.kt
@Module
class AppModule {
    @Provides
    fun provideLogging(): Logging {
        return RemoteLogging()
    }
}

// app/src/main/java/com/example/app/AppComponent.kt
@Component(modules = [AppModule::class, CoreModule::class])
interface AppComponent : CoreComponent {
    // 注入到Android组件(如Activity)
    fun inject(activity: MainActivity)
}

编译时Dagger会生成AppComponent的实现,自动继承CoreComponent的所有依赖声明,同时用AppModule提供的RemoteLogging满足Logging的依赖需求。

使用方式

在App中初始化AppComponent,获取业务逻辑实例时,Logging会自动注入真实实现:

// app/src/main/java/com/example/app/MainActivity.kt
class MainActivity : AppCompatActivity() {
    private lateinit var businessLogic: BusinessLogic

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val appComponent = DaggerAppComponent.create()
        businessLogic = appComponent.businessLogic()
        businessLogic.execute() // 此时使用的是RemoteLogging
    }
}

方案二:Dummy实现+编译时覆盖

如果偏好更简单的模块依赖方式,可以在core模块提供一个空实现的DummyLogging,让模块能编译,再在app模块用真实实现覆盖这个绑定。

步骤1:Core模块添加Dummy实现

修改core模块的CoreModule,添加默认的DummyLogging绑定:

// core/src/main/java/com/example/core/CoreModule.kt
@Module
class CoreModule {
    @Provides
    fun provideLogging(): Logging {
        // 空实现,仅用于core模块编译
        return DummyLogging()
    }

    @Provides
    fun provideBusinessLogic(logging: Logging): BusinessLogic {
        return BusinessLogic(logging)
    }
}

// core/src/main/java/com/example/core/DummyLogging.kt
class DummyLogging : Logging {
    override fun log(message: String) {}
    override fun logError(throwable: Throwable) {}
}

步骤2:App模块覆盖绑定

app模块的AppModule同样提供RemoteLogging,Dagger会自动优先使用app模块的绑定(同类型依赖中,下游模块的绑定会覆盖上游模块):

// app/src/main/java/com/example/app/AppModule.kt
@Module
class AppModule {
    @Provides
    fun provideLogging(): Logging {
        return RemoteLogging()
    }
}

// app/src/main/java/com/example/app/AppComponent.kt
@Component(modules = [CoreModule::class, AppModule::class])
interface AppComponent {
    fun inject(activity: MainActivity)
    fun businessLogic(): BusinessLogic
}

这种方式无需组件继承,适合简单场景,但不如方案一符合依赖反转原则。

关键注意点

  • 不要用Optional:Dagger只要有明确的绑定就能提供实例,完全不需要用Optional来规避编译错误。
  • 依赖反转核心:core模块只依赖抽象接口,不依赖任何具体实现,所有实现都由下游的app模块提供,这是模块化架构的核心原则。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 05:26:12