Reputation: 585
I have been trying to, unsuccessfully, inject the Parent Fragment into its sub fragments for navigation purposes. I have followed a couple of different posts but I can't seem to understand what am I missing in my implementation.
I have a MainActivity
that contains a ViewPager
with one such page containing EventsFragment
. This fragment in turn has two child fragments EventsListFragment
and EventsDetailFragment
. I wanted to inject EventsFragment
fragment into EventsListFragment
so that I can tell it to navigate to EventsDetailFragment
.
I know this is probably a repetition of the posts below and I really apologize for that but I honestly cannot see what am I missing. These are the posts I've found:
My implementation is as follows:
ApplicationComponent
@Singleton
@Component(modules = [
AndroidSupportInjectionModule::class,
ActivityModule::class,
BaseApplicationModule::class,
ApplicationModule::class])
interface ApplicationComponent : AndroidInjector<AndroidApplication> {
@Component.Builder
abstract class Builder : AndroidInjector.Builder<AndroidApplication>()
}
ActivityModule
@Module(includes = [MainActivityProvider::class])
abstract class ActivityModule{
}
MainActivityProvider
@Module(includes = [EventsFragmentProvider::class])
abstract class MainActivityProvider {
@PerActivity
@ContributesAndroidInjector(modules = [MainActivityModule::class])
abstract fun provideMainActivityFactory(): MainActivity
}
EventsFragmentProvider
@Module(includes = [EventsListProvider::class,
EventsDetailProvider::class])
abstract class EventsFragmentProvider {
@PerFragment
@ContributesAndroidInjector(modules = [EventsFragmentModule::class])
abstract fun provideEventsFragmentFactory(): EventsFragment
}
EventsFragmentModule
@Module
class EventsFragmentModule {
@Binds
abstract fun providesEventListView(eventsFragment: EventsFragment): EventContract.Flow
}
EventsListProvider
@Module
abstract class EventsListProvider {
@PerFragment
@ContributesAndroidInjector(modules = [EventsListModule::class])
abstract fun provideEventsListFragmentFactory(): EventsListFragment
}
EventsFragment
class EventsFragment : DaggerFragment(), EventContract.Flow {
override fun navigateToList() {
addFragment(navigator.getEventsListFragment(context!!))
}
override fun navigateToDetail(id: String) {
println("id = ${id}")
}
...
}
EventContract
interface EventContract {
interface Flow {
fun navigateToList()
fun navigateToDetail(id: String)
}
}
EventsListFragment
class EventsListFragment : DaggerFragment() {
@Inject
lateinit var eventsFlow: EventContract.Flow
...
}
[Dagger/MissingBinding] [dagger.android.AndroidInjector.inject(T)] EventContract.Flow cannot be provided without an @Provides-annotated method.
public abstract interface ApplicationComponent extends dagger.android.AndroidInjector<AndroidApplication> {
^
EventContract.Flow is injected at
EventsListFragment.eventsFlow
EventsListFragment is injected at
dagger.android.AndroidInjector.inject(T)
component path: ApplicationComponent →EventsListProvider_ProvideEventsListFragmentFactory.EventsListFragmentSubcomponent
I may be using a anti-pattern but this is what got me working to this point. Im open to changes that may help me achieve this
Upvotes: 0
Views: 1135
Reputation: 1888
The error is caused by the following module:
@Module
class EventsFragmentModule {
@Binds
abstract fun providesEventListView(eventsFragment: EventsFragment): EventContract.Flow
}
Dagger would not provide you with a Fragment
and you shouldn't do that.
Moreover, I think you misunderstand the meaning of @ContributesAndroidInjector
. It means creating an AndroidInjector
for you but proving an instance.
@Module
abstract class EventsListProvider {
@PerFragment
@ContributesAndroidInjector(modules = [EventsListModule::class])
abstract fun provideEventsListFragmentFactory(): EventsListFragment
}
So you should pass your EventsFragment
instance into the module like this post instead of using field injection.
Upvotes: 1