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:
Dagger 2.10 Android subcomponents and builders
How to create custom scoped modules in dagger 2.10
https://google.github.io/dagger/subcomponents.html
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
...
}
Error
[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
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.
Related
Dagger 2
/di/AppComponent.java:19: error: [Dagger/MissingBinding] ProductListFragment cannot be provided without an #Inject constructor or an #Provides-annotated method. This type supports members injection but cannot be implicitly provided.
public abstract interface AppComponent {
^
A binding with matching key exists in component: MainFragmentProvider_BindProductListFragment.ProductListFragmentSubcomponent
ProductListFragment is injected at
productlist.ProductListModule.provideChildFragmentManager(productListFragment)
androidx.fragment.app.FragmentManager is injected at
productlist.adapter.NewProductListPagerAdapter(…, fragmentManager)
productlist.adapter.NewProductListPagerAdapter is injected at
productlist.ProductListV2Fragment.mPagerAdapter
productlist.ProductListV2Fragment is injected at
dagger.android.AndroidInjector.inject(T) [di.AppComponent → di.BuilderModule_BindMainActivity.MainActivitySubcomponent → MainFragmentProvider_BindProductListV2Fragment.ProductListV2FragmentSubcomponent]
I have the following module with these 2 fragments here:
#Module
abstract class FragmentProvider {
#PerFragment
#ContributesAndroidInjector(modules = [ProductListModule::class])
abstract fun bindProductListV2Fragment(): ProductListV2Fragment
#PerFragment
#ContributesAndroidInjector(modules = [ProductListModule::class])
abstract fun bindProductListFragment(): ProductListFragment
}
In my ProductListModule I have the following:
#Module
class ProductListModule {
#Provides
fun provideChildFragmentManager(productListFragment: ProductListFragment) =
productListFragment.childFragmentManager
}
The fragmentManager will be injected into the following class:
class NewProductListPagerAdapter #Inject constructor(
#ActivityContext private val context: Context,
fragmentManager: FragmentManager
) { ..... }
And both fragments will inject this NewProductListPagerAdapter in them.
class ProductListV2Fragment : BaseProductListFragment() {
#Inject
lateinit var mPagerAdapter: NewProductListPagerAdapter
}
class ProductListFragment : BaseProductListFragment() {
#Inject
lateinit var mPagerAdapter: NewProductListPagerAdapter
}
My AppComponent:
#Singleton
#Component(
modules = [
AndroidSupportInjectionModule::class,
AppModule::class,
ProductModule::class,
BaseAppModule::class
]
)
interface AppComponent {
#Component.Factory
interface Factory {
fun create(
#BindsInstance application: Application,
): AppComponent
}
fun inject(tsApplication: TsApplication)
}
==== UPDATE ====
#Module
abstract class FragmentProvider {
#PerFragment
#ContributesAndroidInjector(modules = [ProductListModule::class, ProductListBindingModule::class])
abstract fun bindProductListFragment(): ProductListFragment
#PerFragment
#ContributesAndroidInjector(modules = [ProductListModule::class, ProductListV2BindingModule::class])
abstract fun bindProductListV2Fragment(): ProductListV2Fragment
}
#Module
class ProductListModule {
#Provides
fun provideChildFragmentManager(productListFragment: Fragment): FragmentManager =
productListFragment.childFragmentManager
}
#Module
abstract class ProductListBindingModule {
#Binds
abstract fun bindFragment(fragment: ProductListFragment): Fragment
}
#Module
abstract class ProductListV2BindingModule {
#Binds
abstract fun bindFragment(fragment: ProductListV2Fragment): Fragment
}
The stack trace is below which is indicating that the Fragment is bound multiple times. The reason being is because each fragment injects the following dependency:
#Inject
lateinit var mPagerAdapter: NewProductListPagerAdapter
And in the NewProductListPagerAdapter constructor:
class NewProductListPagerAdapter #Inject constructor(
#ActivityContext private val context: Context,
fragmentManager: FragmentManager
)
Which needs to provide the FragmentManager;
app/build/tmp/kapt3/stubs/uatDebug/tech/central/tops/di/AppComponent.java:22: error: [Dagger/DuplicateBindings] androidx.fragment.app.Fragment is bound multiple times:
public abstract interface AppComponent {
#org.jetbrains.annotations.NotNull #Binds androidx.fragment.app.Fragment productlist.ProductListBindingModule.bindFragment(productlist.ProductListFragment)
#org.jetbrains.annotations.NotNull #Binds androidx.fragment.app.Fragment productlist.ProductListV2BindingModule.bindFragment(productlist.ProductListV2Fragment)
androidx.fragment.app.Fragment is injected at
authentication.usecase.FacebookLoginUseCase(fragment, …)
authentication.usecase.FacebookLoginUseCase is injected at
authentication.usecase.SocialLoginUseCase(…, facebookLoginUseCase, …)
authentication.usecase.SocialLoginUseCase is injected at
authentication.FacebookLoginViewModel(…, socialLoginUseCase, …)
authentication.FacebookLoginViewModel is injected at
authentication.FacebookLoginViewModelModule.facebookViewModelChildFactory(facebookLoginViewModel)
java.util.Map<java.lang.Class<? extends androidx.lifecycle.ViewModel>,javax.inject.Provider<androidx.lifecycle.ViewModel>> is injected at
di.factory.ViewModelProviderFactory(classToViewModel)
di.factory.ViewModelProviderFactory is injected at
.authentication.login.LoginFragment.mViewModelChildFactory
authentication.login.LoginFragment is injected at
dagger.android.AndroidInjector.inject(T) [tech.central.tops.di.AppComponent → di.BuilderModule_BindMainActivity.MainActivitySubcomponent → FragmentProvider_BindLoginFragment.LoginFragmentSubcomponent]
Your module depends on ProductListFragment to obtain a child FragmentManager. However, that same module is used to inject into ProductListV2Fragment, and there is no ProductListFragment available at that point.
In order to reuse that module, you will need to split the dependency on ProductListFragment into a separate module. This module should be used for ProductListFragment, and a similar module should be used for ProductListV2Fragment. In these modules, you can either provide FragmentManager directly or bind both fragments to a common superclass such as Fragment or BaseProductListFragment.
If you bind both fragments to Fragment, the resulting code will look like this:
#Module
abstract class FragmentProvider {
#PerFragment
#ContributesAndroidInjector(modules = [
ProductListModule::class,
ProductListV2BindingModule::class
])
abstract fun bindProductListV2Fragment(): ProductListV2Fragment
#PerFragment
#ContributesAndroidInjector(modules = [
ProductListModule::class,
ProductListBindingModule::class
])
abstract fun bindProductListFragment(): ProductListFragment
}
#Module
class ProductListModule {
#Provides
fun provideChildFragmentManager(productListFragment: Fragment) =
productListFragment.childFragmentManager
}
#Module
abstract class ProductListBindingModule {
#Binds
fun bindFragment(fragment: ProductListFragment): Fragment
}
#Module
abstract class ProductListV2BindingModule {
#Binds
fun bindFragment(fragment: ProductListV2Fragment): Fragment
}
As for the error message itself, it tells you three things:
The generated ProductListV2FragmentSubcomponent requires a ProductListFragment, but there is no available binding for it.
The subcomponent may be able to inject dependencies into an existing ProductListFragment. This can be useful information in other situations, but it isn't relevant to what you're trying to do.
There is a component in your app which can provide ProductListFragment. Specifically, this is the generated ProductListFragmentSubcomponent, which takes a ProductListFragment in its factory.
#Module
abstract class PersonUsecaseModule{
#Provides
internal fun provideUseCase(useCase: GetPersonUseCaseImpl): PersonUseCase = useCase
#Provides
internal fun provideMutableLiveData() = MutableLiveData<PersonUseCase.Result>()
#Provides
internal fun providePersonWidgetImplScreen(widget: PersonWidgetImpl): PersonWidget = widget
}
this is my module class and i am injecting it in MainActivity i am getting error
error: com.anil.gorestapp.person.injection.PersonUsecaseModule is abstract and has instance #Provides methods. Consider making the methods static or including a non-abstract subclass of the module instead.
public abstract interface ApplicationComponent {
I don't know why i am getting this Error Please help me what i am doing mistake
lateinit var personWidget: PersonWidget
AppLication component :
#Singleton
#Component(
modules = [
ApplicationModule::class,
ActivityModule::class,
NetworkModule::class
]
)
interface ApplicationComponent {
#Component.Builder
interface Builder {
#BindsInstance
fun application(application: Application): Builder
fun build(): ApplicationComponent
}
fun inject(application: MainApplication)
}
ActivityModule
abstract class ActivityModule {
#ContributesAndroidInjector
abstract fun contributeMainActivity(): MainActivity
#Binds
abstract fun bindSharedPreferences(appPreferenceImpl: AppPreferenceImpl): AppPreference
}
person module
abstract class ActivityModule {
#ContributesAndroidInjector
abstract fun contributeMainActivity(): MainActivity
#Binds
abstract fun bindSharedPreferences(appPreferenceImpl: AppPreferenceImpl): AppPreference
}
So the issue is, You have declared your module as "abstract" and along with this, you are also using #Provides annotation on methods which are returning implementation of interface.
Dagger doesn't allow that. You can fix this issue in two way:
First Way: Remove abstract from your module like this:
#Module
class ActivityModule {
#Provides
fun providePersonWidget(personWidget: PersonWidgetImpl) : PersonWidget = personWidget
}
Second way: Use #Bind annotation on method instead of provide like this
#Module
abstract class ActivityModule {
#Binds
abstract fun providePersonWidget(personWidget: PersonWidgetImpl) : PersonWidget
}
Note: In second way you can declare your method and class as abstract but cannot return anything.
If you are still not very clear with my answer, you can refer this branch which I have created for you.
https://github.com/parmeshtoyou/StackOverflow/compare/sof_23_oct_21_dagger_issue?expand=1
I've two modules :app and :settings. Here are my dagger configuration.
My component:
#ApplicationScope
#Component(
modules = [
AndroidInjectionModule::class,
AndroidSupportInjectionModule::class,
RoutingModule::class,
SettingsModule::class
]
)
interface ELanguageComponent {
#Component.Builder
interface Builder {
#BindsInstance
fun application(application: Application): Builder
fun build(): ELanguageComponent
}
fun inject(application: BaseELanguageApplication)
}
The RoutingModule:
#Module
class RoutingModule {
#Provides
fun ProvidesettingsFragmentRouter(router: SettingsRouter): SettingsFragment.Router = router
}
The SettingsRouter:
class SettingsRouter #Inject constructor(
private val applicationStateManager: ApplicationStateManager
) : SettingsFragment.Router
The SettingsModule:
#Module
abstract class SettingsModule {
#ActivityScope
#ContributesAndroidInjector(modules = [SettingsFragmentModule::class, ApplicationStateManagerModule::class])
abstract fun settingsActivity(): SettingsActivity
}
#Module
abstract class ApplicationStateManagerModule {
#Module
companion object {
#JvmStatic
#Provides
fun bindApplicationStateManager(settingsActivity: SettingsActivity): ApplicationStateManager = settingsActivity
}
}
My SettingsFragmentModule:
#Module
abstract class SettingsFragmentModule {
#FragmentScope
#ContributesAndroidInjector
abstract fun settingsFragment(): SettingsFragment
}
And the SettingsFragment.Router is injected inside my SettingsFragment:
class SettingsFragment : DaggerFragment() {
#Inject
lateinit var router: Router
...
}
I've already found and read this article but it does not help much since the error is not that explanatory:
[Dagger/MissingBinding]
com.altissia.common.authentication.ApplicationStateManager cannot be
provided without an #Provides-annotated method. public abstract
interface ELanguageComponent {
^
com.altissia.common.authentication.ApplicationStateManager is injected at
com.altissia.router.SettingsRouter(applicationStateManager, …)
com.altissia.router.SettingsRouter is injected at
com.altissia.injection.module.RoutingModule.ProvidesettingsFragmentRouter(router)
com.altissia.settings.fragment.SettingsFragment.Router is injected at
com.altissia.settings.fragment.SettingsFragment.router
com.altissia.settings.fragment.SettingsFragment is injected at
dagger.android.AndroidInjector.inject(T) [com.altissia.injection.component.ELanguageComponent →
com.altissia.settings.injection.module.SettingsModule_SettingsActivity.SettingsActivitySubcomponent
→
com.altissia.settings.injection.module.SettingsFragmentModule_SettingsFragment.SettingsFragmentSubcomponent]
What am I missing here? ApplicationStateManager is provided through the ApplicationStateManagerModule which is installed inside SettingsModule.
The situation in the linked article applies here.
SettingsFragment requests a SettingsFragment.Router.
SettingsFragment.Router depends on SettingsRouter, and this binding is in the application component.
SettingsRouter depends on ApplicationStateManager via an #Inject constructor.
The ApplicationStateManager binding is in your (generated) activity subcomponent.
Thus, you have a binding in the parent component which requires a binding in a subcomponent. As described in the article, the easiest way to fix this is to move RoutingModule into your activity (or fragment) subcomponent.
You should add SettingsFragment to SettingsActivity using a contributor module
#ActivityScope
#ContributesAndroidInjector(modules = [
ApplicationStateManagerModule::class,
FragmentContributorModule::class])
abstract fun settingsActivity(): SettingsActivity
And contributor module is something like this
#Module
abstract class FragmentContributorModule {
#FragmentScope
#ContributesAndroidInjector(modules = [SettingsFragmentModule::class])
abstract fun contributeSettingsFragment(): SettingsFragment
}
My setup that i used to use with dagger-android was
AppComponent
#Component(modules = [
AndroidSupportInjectionModule::class,
AppModule::class,
ActivityContributorModule::class])
/*
* ActivityContributorModule defines which Activities will have which modules and inject objects
* If an Activity has any fragments it should add them via FragmentContributorModule with #ContributesAndroidInjector
* #ContributesAndroidInjector(modules = {MainActivityModule.class, FragmentContributorModule.class})
*/
#Singleton
interface AppComponent : AndroidInjector<MyApplication> {
#Component.Builder
interface Builder {
#BindsInstance
fun application(application: Application): Builder
fun build(): AppComponent
}
override fun inject(myApplication: MyApplication)
}
and Activity set up with ActivityContributorModule
#Module
abstract class ActivityContributorModule {
#ActivityScope
#ContributesAndroidInjector(modules = [MainActivityModule::class, FragmentContributorModule::class])
abstract fun contributeMainActivity(): MainActivity
#ActivityScope
#ContributesAndroidInjector(modules = [SecondActivityModule::class])
abstract fun contributeSecondActivity(): SecondActivity
#ActivityScope
#ContributesAndroidInjector
abstract fun contributeThirdActivity(): ThirdActivity
}
And for the fragments to be used by Activities
#Module
abstract class FragmentContributorModule {
/**
* FragmentContributorModule is used inside ActivityContributorModule
* With #ContributesAndroidInjector(modules = MyFragmentModule.class)
* defines which module will be used to inject objects to MyFragment
*
*
* In this example [MainActivity] has [FirstFragment] fragment1, and [FirstFragment]
* uses [FirstFragmentModule] to inject objects
*
*
*
* Scope of #ContributesAndroidInjector methods and their modules should be same.
* Otherwise app returns HAS CONFLICTING SCOPES error
*
*/
#FragmentScope
#ContributesAndroidInjector(modules = [FirstFragmentModule::class])
abstract fun contributeMyFragment(): FirstFragment
}
This is obsolete since the Dagger Hilt came out. It's much easier to implement dependency injection.
You can check out this github link you can refer both for dagger-android with scoped components or Hilt implementations.
Hello I'm new to Dagger and I have crated a simple project to learn more about it. I have a class PermissionManager that has activity as constructor parameter
class PermissionManager(activity: MainActivity) {
}
and my MainFragment has a dependency on it. So I created BindingModule
#Module
interface BindingModule {
#DaggerScope(MainActivity::class)
#ContributesAndroidInjector(modules = [MainActivityModule::class])
fun provideMainActivity(): MainActivity
#FragmentScope
#ContributesAndroidInjector(modules = [MainFragmentModule::class])
fun provideMainFragment(): MainFragment
}
Here's my MainActivityModule that provides PermissionManager
#Module
abstract class MainActivityModule private constructor() {
#Module
companion object {
#Provides
#JvmStatic
fun providePermissionManager(activity: MainActivity): PermissionManager = PermissionManager(activity)
}
}
and here's my MainFragmentModule that has to use PermissionManager that was created in my MainActivityModule
#Module
abstract class MainFragmentModule private constructor() {
#Module
companion object {
#JvmStatic
#Provides
#IntoMap
#ViewModelKey(MyTestViewModel::class)
fun provideModelFactory(
permissionManager: PermissionManager
): ViewModel = MyTestViewModel(permissionManager)
}
}
and here's what I get
com\nav\component\di\AppComponent.java:12: error: [Dagger/MissingBinding] com.nav.component.utils.PermissionManager cannot be provided without an #Inject constructor or an #Provides-annotated method.
public abstract interface AppComponent extends dagger.android.AndroidInjector<com.nav.component.MyTestDaggerApp>
So first of all I don't understand why I can't use dependency that was created for activity in my fragment? Any ideas how to solve this?
EDIT:
Here's how Binding Module is used
#AppScope
#Component(
modules = [
AndroidSupportInjectionModule::class,
AppModule::class,
BindingModule::class,
NetworkingModule::class
]
)
interface AppComponent : AndroidInjector<MyTestDaggerApp> {
/**
* AppComponent Builder interface. All implementation part is handled by a dagger compiler.
*/
#Component.Factory
interface Factory : AndroidInjector.Factory<MyTestDaggerApp>
}
Make your fragment a subcomponent of BindingModule to get bindings from it. Don't forget to make MainActivity implement HasAndroidInjector (if it doesn’t already).
#Module
interface BindingModule {
#DaggerScope(MainActivity::class)
#ContributesAndroidInjector(modules = [MainActivityModule::class, MainFragmentBindingModule::class])
fun provideMainActivity(): MainActivity
}
#Module
interface MainFragmentBindingModule {
#FragmentScope
#ContributesAndroidInjector(modules = [MainFragmentModule::class])
fun provideMainFragment(): MainFragment
}
I am using Dagger 2.16 and was following this article for my dagger implementation. Everything was working fine with this implementation until I had only one Activity(HomeActivity). As soon as I started implementing Dagger in SplashScreenActivity. I started getting this error. Here is some code from my project
AppComponent.kt
#Singleton
#Component(modules = [
AndroidInjectionModule::class,
AppModule::class,
ActivityBuilder::class,
ServiceBuilder::class,
BroadcastRecieverBuilder::class])
interface AppComponent : AndroidInjector<MyApp> {
#Component.Builder
abstract class Builder : AndroidInjector.Builder<MyApp>()
}
AppModule.kt
#Module()
class AppModule {
#Provides
#Singleton
fun provideContext(application: MyApp): Context {
return application
}
#Provides
#Singleton
fun provideRestService(retrofit: Retrofit): RestService {
return retrofit.create(RestService::class.java)
}
...
}
ActivityBuilder.kt
#Module
abstract class ActivityBuilder {
#ContributesAndroidInjector(modules = [HomeActivityModule::class])
#PerActivity
abstract fun bindHomeActivity(): HomeActivity
#ContributesAndroidInjector(modules = [SplashScreenModule::class])
#PerActivity
abstract fun bindSplashActivity(): SplashScreenActivity
}
BaseActivity.kt
abstract class BaseActivity<V : BaseView, P : MvpBasePresenter<V>> :
MvpActivity<V, P>(), BaseView, HasSupportFragmentInjector {
#Inject
lateinit var fragmentInjector: DispatchingAndroidInjector<Fragment>
#Inject
lateinit var mPresenter: P
override fun onCreate(savedInstanceState: Bundle?) {
AndroidInjection.inject(this)
super.onCreate(savedInstanceState)
}
override fun createPresenter(): P = mPresenter
override fun supportFragmentInjector(): AndroidInjector<Fragment> {
return fragmentInjector
}
}
I have my own BaseActivity instead of DaggerActivity because I what to inherit from mosby's MvpActivity.
SplashScreenModule.kt
#Module
abstract class SplashScreenModule {
#Binds
#PerActivity
internal abstract fun splashPresenter(splashPresenter: SplashScreenPresenter): BasePresenter<*>
}
HomeActivityModule.kt
#Module
abstract class HomeActivityModule {
#Binds
#PerActivity
internal abstract fun homePresenter(homePresenter: HomeActivityPresenter): BasePresenter<*>
#ContributesAndroidInjector(modules = [DownloadFragmentModule::class])
#PerFragment
internal abstract fun downloadsFragment(): DownloadsFragment
}
Now when I build this, I get an error as follows
error: [Dagger/MissingBinding] [dagger.android.AndroidInjector.inject(T)] java.util.Map<java.lang.Class<? extends android.support.v4.app.Fragment>,javax.inject.Provider<dagger.android.AndroidInjector.Factory<? extends android.support.v4.app.Fragment>>> cannot be provided without an #Provides-annotated method.
public abstract interface AppComponent extends dagger.android.AndroidInjector<com.realtime.app.MyApp> {
^
A binding with matching key exists in component: com.realtime.dagger.ActivityBuilder_BindHomeActivity.HomeActivitySubcomponent
java.util.Map<java.lang.Class<? extends android.support.v4.app.Fragment>,javax.inject.Provider<dagger.android.AndroidInjector.Factory<? extends android.support.v4.app.Fragment>>> is injected at
dagger.android.DispatchingAndroidInjector.<init>(injectorFactories)
dagger.android.DispatchingAndroidInjector<android.support.v4.app.Fragment> is injected at
com.realtime.core.BaseActivity.fragmentInjector
com.realtime.splashScreen.SplashScreenActivity is injected at
dagger.android.AndroidInjector.inject(T)
component path: com.realtime.dagger.AppComponent → com.realtime.dagger.ActivityBuilder_BindSplashActivity.SplashScreenActivitySubcomponent
I have gone through other similar que like this but couldn't relate it to what I am facing. What am I missing?
Update: For now I am not inheriting BaseActivity in SplashScreenActivity so that I can avoid injecting fragmentInjector: DispatchingAndroidInjector<Fragment>. It is working for now as I don't have any fragment in SplashScreenActivity.
It works for HomeActivity because it binds a fragment:
#ContributesAndroidInjector
fun downloadsFragment(): DownloadsFragment
SplashScreenActivity does not.
AndroidInjection uses DispatchingAndroidInjector to handle runtime injections, which basically contains a Map of classes to their component builders. This map needs to be injected like everything else. In the case of HomeActivity the fragment declaration in the module generates a binding for the map, which can then be injected.
Since there is no Fragment on the splash activity Dagger does not know about any bindings, let alone any map. Which is why it complains that it cannot be provided.
You can read more here about multibindings.
To prevent this from happening, you should register AndroidInjectionModule on your AppComponent, which just contains the declarations for the empty maps.
While it contains the declaration for android.app.Fragment it does not for android.support.v4.app.Fragment, which is where the error comes from.
So to fix this specific error you should add AndroidSupportInjectionModule to your component, which also includes the support bindings, providing an empty map when there are no fragments in an activity.
#Component(modules = [AndroidSupportInjectionModule::class, /* ... */])
interface AppComponent { /* ... */ }