Puntogris
Puntogris

Reputation: 345

How to use dependencies from another Module with Dagger2 in Android?

So i Have AppModule and HomeModule. I would like to use in HomeModule the Application context and AppDatabase from AppModule.

I'm getting this error: AppDatabase cannot be provided without an @Provides-annotated method. public abstract interface HomeComponent

@Singleton
@Component(
    modules = [AppModule::class]
)
interface AppComponent {

@Component.Builder
interface Builder {
    fun build(): AppComponent

    @BindsInstance
    fun application(application: Application): Builder
}
}

This is the AppModule:

@Module
class AppModule {

@Provides
@Singleton
fun provideAppDatabase(app: Application): AppDatabase{
    return Room.databaseBuilder(
        context,
        AppDatabase::class.java,
        "app_db"
    )
        .build()
}

}

@Module

How can i use the AppModule dependencies(in this case AppDatabase and the Application) in the HomeModule ?

@Module
class HomeModule {

@Provides
@Singleton
fun provideHomeDao(appDatabase: AppDatabase): HomeDao {
    return appDatabase.homeDao
}

@Provides
@Singleton
fun provideHomeRepository(homeDao: HomeDao): HomeRepository {
    return HomeRepositoryImpl(homeDao)
}
}

The HomeComponent:

@Singleton
@Component(
    modules = [HomeModule::class]
)

interface HomeComponent {
    fun inject(homeFragment: HomeFragment)
}

Upvotes: 1

Views: 1265

Answers (1)

Mohmmaed-Amleh
Mohmmaed-Amleh

Reputation: 438

It will not work because they are unrelated to each other. The solution is:

The HomeComponent:

@FragmentScope
@Subcomponent(
    modules = [HomeModule::class]
)

interface HomeComponent {
    fun inject(homeFragment: HomeFragment)
}

@Scope
@Documented
@Retention(RetentionPolicy.RUNTIME)
annotation class FragmentScope

Explanation: We should use HomeComponent as subcomponent for AppCompnent and we should use another annotation to avoid conflict.

The AppComponent:

@Singleton
@Component(modules = [AppModule::class])
interface AppComponent {

    fun getHomeFragmentCompnent():HomeComponent

    @Component.Builder
    interface Builder {
        fun build(): AppComponent

        @BindsInstance
        fun application(application: Application): Builder
    }
}

Then in your Fragment you can use it like this, for example:

@FragmentScope
class AnyFragment:Fragment {

    @Inject
    lateinit var dao: HomeDao 

    //in onCreateView
    val component = ((application as YourApplcation).applicationComponent)
        .getHomeFragmentCompnent().inject(this)
}

Upvotes: 2

Related Questions