1

My app has a library (Core Library) we maintain as a module in the project and we include as a gradle dependency like this:

build.gradle

dependencies {
    api project(':core')
}

I'm trying to integrate this Core Library as a Dagger subcomponent the way it's shown on this RW tutorial.

The problem I'm facing is that all of the @Provides annotated methods inside CoreModule can't be found and when digging into the compiled DaggerAppComponent generated file, the corresponding providing methods are missing, even though they're supposed to be annotated correctly. Do you guys have an idea of I'm doing wrong?

This is the error message I get. CoreSettings is annotated as a @Provides method but still can't be found.

android/di/AppComponent.java:12: error: [Dagger/MissingBinding] com.core.util.CoreSettings cannot be provided without an @Inject constructor or an @Provides-annotated method.
    public abstract interface AppComponent {
                    ^
          com.core.util.CoreSettings is injected at com.base.BaseVideoPlayerActivity.coreSettings
      com.base.BaseVideoPlayerActivity is injected at
          com.di.AppComponent.inject(com.base.BaseVideoPlayerActivity)
  It is also requested at:
      com.base.BaseVideoPlayerActivity.coreSettings
  The following other entry points also depend on it:
      com.di.AppComponent.inject(com.ui.LiveVideoActivity)

DaggerAppComponent.java (Here the provider method for CoreSettings, declared in CoreModule, is missing)

private final class CoreComponentImpl implements CoreComponent {
    private CoreComponentImpl() {

    }

    @Override
    public void inject(FeedDownloadService arg0) {
    }
  }

I have tried many different things like including the CoreModule directly in the AppComponent which works wonderfully, but not when it's part of the subcomponent.

Here is the file breakdown:

AppComponent.kt

@ApplicationScope
@Component(modules = [UtilsModule::class, CoreLibraryModule::class])
interface AppComponent {

    @Component.Factory
    interface Factory {
        fun create(modules: UtilsModule): AppComponent
    }
    
    fun coreComponentFactory(): CoreComponent.Factory

    /**
     * Classes that can be injected by this Component
     */
    fun inject(app: AppApplication)
}

UtilsModule.kt

@Module
class UtilsModule(private val ctx: Context) {

    @ApplicationScope
    @Provides
    fun provideApplicationContext(): Context = ctx
}

CoreLibraryModule.kt

/**
 * Wrapper module for the CoreComponent to be included in the AppComponent
 */
@Module(subcomponents = [CoreComponent::class, SplashComponent::class])
object CoreLibraryModule

CoreComponentProvider.kt

/**
 * Interface that provides a CoreComponent that Core Library classes can use for injection.
 * This interface must be implemented by the Application subclass.
 */
interface CoreComponentProvider {
    fun getCoreComponentFactory(): CoreComponent.Factory
}

CoreComponent.kt

/**
 * Subcomponent that provides injection mechanism to Core Library classes
 */
@Subcomponent(modules = [CoreModule::class])
interface CoreComponent {

    @Subcomponent.Factory
    interface Factory {
        fun create(module: CoreModule): CoreComponent
    }

    /**
     * Classes that can be injected by this Component
     */
    fun inject(app: FeedDownloadService)
}

CoreModule.kt

@Module
class CoreModule {

    @ApplicationScope
    @Provides
    fun provideCoreSettings(): CoreSettings = CoreSettings.getInstance()
}

BaseVideoPlayerActivity.kt

class BaseVideoPlayerActivity: Activity {

    @Inject
    lateinit var coreSettings: CoreSettings

    override fun onCreate(savedInstanceState: Bundle?) {
        // Inject dependencies via Dagger here.
        (application as AppApplication).appComponent.inject(this)
    }
}
kriztho
  • 300
  • 2
  • 14

0 Answers0