0

I am modularizing one of my Android App. In which I am using Dagger for Dependency Injection. It was working fine with one module.

But since I created 3 modules now I am facing many issues mainly because of Dagger. Modules inr app are app, core, feature. I am trying to keep all shared code in the base module. So I have integrated Dagger in my core module using article. When I trying to use custom Scope (ie AppScope) for my AppComponent in order to connect it with the core module. I am getting below error. However Singleton is working.

E:\shahbaz\ultimate-downloader\app\build\tmp\kapt3\stubs\debug\matrixsystems\ultimatedownloader\di\components\AppComponent.java:12: error: [Dagger/IncompatiblyScopedBindings] matrixsystems.ultimatedownloader.di.components.AppComponent scoped with @matrixsystems.ultimatedownloader.di.AppScope may not reference bindings with different scopes:
public abstract interface AppComponent {

Code I am using :

AppComponent.kt

@AppScope // Singleton is working
@Component(modules = [AndroidInjectionModule::class, AppModule::class])
interface AppComponent {

@Component.Builder
interface Builder {

    @BindsInstance
    fun application(app: AppController): Builder

    fun build(): AppComponent
}

fun inject(app: AppController)

}

AppModule.kt

@Module(includes = [ActivityModule::class, ViewModelModule::class])
class AppModule {

/**
 * Application application level context.
 */
@Singleton
@Provides
fun provideContext(application: AppController): Context {
    return application.applicationContext
}


/**
 * Application resource provider, so that we can get the Drawable, Color, String etc at runtime
 */
@Provides
@Singleton
fun providesResources(application: AppController): Resources = application.resources

}

ActivityModule.kt

@Module(includes = [FragmentModule::class]) // Including Fragment Module Available For Activities
internal abstract class ActivityModule {

/**
 * Marking Activities to be available to contributes for Android Injector
 */
@ContributesAndroidInjector
abstract fun contributeMainActivity(): MainActivity

}

FragmentModule.kt

@Module
internal abstract class FragmentModule {

@ContributesAndroidInjector
internal abstract fun contributeDownloadsFragment(): DownloadsFragment
}

ViewModelModule.kt

@Module
internal abstract class ViewModelModule {

@Binds
@IntoMap
@ViewModelKey(MainViewModel::class)
abstract fun bindMainViewModel(mainViewModel: MainViewModel): ViewModel

@Binds
@IntoMap
@ViewModelKey(DownloadsViewModel::class)
abstract fun bindDownloadsViewModel(downloadsViewModel: DownloadsViewModel): ViewModel

/**
 * Binds ViewModels factory to provide ViewModels.
 */
@Binds
abstract fun bindViewModelFactory(factory: ViewModelFactory): ViewModelProvider.Factory

}

AppController.kt

class AppController : Application(), HasActivityInjector {
@Inject
lateinit var dispatchingAndroidInjector: DispatchingAndroidInjector<Activity>

override fun onCreate() {
    super.onCreate()
    AppInjector.initApp(this)
}

override fun activityInjector(): AndroidInjector<Activity> {
    return dispatchingAndroidInjector
}
}

AppInjector.kt

object AppInjector {

fun initApp(app: AppController) {
    DaggerAppComponent.builder().application(app).build().inject(app)

    app.registerActivityLifecycleCallbacks(object :
        Application.ActivityLifecycleCallbacks {
        override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
            handleActivity(activity)
        }

        override fun onActivityStarted(activity: Activity) {}

        override fun onActivityResumed(activity: Activity) {}

        override fun onActivityPaused(activity: Activity) {}

        override fun onActivityStopped(activity: Activity) {}

        override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {}

        override fun onActivityDestroyed(activity: Activity) {}
    })
}

private fun handleActivity(activity: Activity) {
    if (activity is HasSupportFragmentInjector) {
        AndroidInjection.inject(activity)
    }
    (activity as? FragmentActivity)?.supportFragmentManager?.registerFragmentLifecycleCallbacks(
        object : FragmentManager.FragmentLifecycleCallbacks() {
            override fun onFragmentCreated(
                fm: FragmentManager,
                f: Fragment,
                savedInstanceState: Bundle?
            ) {
                if (f is Injectable) {
                    AndroidSupportInjection.inject(f)
                }
            }
        }, true
    )
}
}

I have spent 2 days but still no luck. I just want to add functional core module with Dagger. Any working article or sample code which I can use without making much changes in my existing app module is highly appreciated.

Shahbaz Hashmi
  • 2,631
  • 2
  • 26
  • 49
  • use `@Singleton` or change all `@Singleton`'s to your `@AppScope` – IR42 May 01 '20 at 10:30
  • @IR42 read my question again – Shahbaz Hashmi May 01 '20 at 10:33
  • you can't use different scopes in component and its modules, so read my comment again – IR42 May 01 '20 at 11:11
  • @IR42 there are tons of blogs on how to use custom scope in component. Even the link I added in question has same thing. If you can provide me the answer you are welcome. Just post it I will accept and upvote. – Shahbaz Hashmi May 01 '20 at 11:16
  • In the example of the article: [AppComponent with @AppScope](https://github.com/marcosholgado/dagger-playground/blob/multi-module-dagger-android/app/src/main/java/com/marcosholgado/daggerplayground/di/AppComponent.kt), its [AppModule](https://github.com/marcosholgado/dagger-playground/blob/multi-module-dagger-android/app/src/main/java/com/marcosholgado/daggerplayground/di/AppModule.kt) with unscoped method (it means that this dependency will be re created all the time) – IR42 May 01 '20 at 13:20
  • and there is [CoreComponent with @Singleton](https://github.com/marcosholgado/dagger-playground/blob/multi-module-dagger-android/core/src/main/java/com/marcosholgado/core/di/CoreComponent.kt) and its [CoreModule](https://github.com/marcosholgado/dagger-playground/blob/multi-module-dagger-android/core/src/main/java/com/marcosholgado/core/di/CoreModule.kt) with Singleton scoped method – IR42 May 01 '20 at 13:21
  • Dear @IR42 I cannot use Singleton here as per the article I am using. If you have the answer you can post it. – Shahbaz Hashmi May 01 '20 at 16:45
  • Does this answer your question? [CustomScope may not reference bindings with different scopes](https://stackoverflow.com/questions/53791779/customscope-may-not-reference-bindings-with-different-scopes) – denvercoder9 May 02 '20 at 21:46
  • @IR42 is right. See the [documentation](https://dagger.dev/api/latest/dagger/Component.html#scope) – denvercoder9 May 02 '20 at 21:47

0 Answers0