0
votes

I have an application using Dagger 2 having AppScope which has ActivityScope beneath it, which in turn contains FragmentScope. the Fragment @Inject fields can be injected with @Provides methods of the AppModule, and ActivityModule but not the @Provides methods inside the FragmentModule.

I made sure to include the FragmentModule in the subcomponent of the Fragment. Also there is no need to make sure that the Fragment is scoped properly under the activity and the app because it is already successful of getting dependencies from their modules.

Here is the FragmentModule:

@Module
class SecondFragmentModule {

    @Module
    companion object {
        @JvmStatic
        @Provides
        fun provideString() : String {
            return "string"
        }
    }
}

Here is the FragmentBuildersModule

@Module
abstract class FragmentsBuilderModule {

    @ContributesAndroidInjector
    abstract fun contributeFirstFragmentFragment() : FirstFragment

    @ContributesAndroidInjector(modules = [SecondFragmentModule::class])
    abstract fun contributeSecondFragment() : SecondFragment

    @ContributesAndroidInjector
    abstract fun contributeSettingsFragment() : SettingsFragment
}

Here is the ActivityBuilderModule which contains the FragmentsBuildersModule as u can c:

@Module
abstract class ActivityBuildersModule {

    @ContributesAndroidInjector(modules = [
        ActivityViewModelModule::class,
        ActivityModule::class,
        FragmentsBuilderModule::class,
        FragmentsViewModelsModule::class
    ])
    abstract fun contributeHomeActivity() : HomeActivity
}

NOTE: There is not mistake at all in the spelling in the real project, I had to change some names to make the question general and to make it easy for developers trying to help, this might led to some mistakes in spelling but this is not the case in the project itself.

EDIT:

Sorry, I checked the @Inject fields in the Fragment they get injected normally my problem is the @Inject constructor of the Repository needed by the FragmentViewModel, the fields of that repository can't be inject from the dependencies of the FragmentModule but can only injected from deps of the ActivityModule and the AppModule.

The ViewModel class: The repository is injected without any problem because the repository has @Inject constructor

class FragmentViewModel @Inject constructor(var repository: 
    FragmentRepository) : ViewModel() {

    lateinit var mediatorLiveData:MediatorLiveData<MutableList<POJO>>

    fun getDataFromApi() {
        mediatorLiveData = repository.getDataFromApi()
    } 
}

The Repository class:

class FragmentRepository @Inject constructor(var database: 
FirebaseFirestore, var collectionName: String) {

    private val mediatorLiveData:MediatorLiveData<MutableList<POJO>> = MediatorLiveData()

    fun getDataFromApi() : MediatorLiveData<MutableList<POJO>> {
        val dataListLD: MutableList<POJO> = ArrayList()
        database
            .collection(collectionName)
            .get()
            .addOnSuccessListener { result ->
                for (document in result) {
                    val dataObj = document.toObject(POJO::class.java)
                    dataListLD.add(dataObj)
                }
                mediatorLiveData.value = dataListLD
            }
        return mediatorLiveData
    }
}

When I try to @Provide the dependency needed by the repository in the FragmentModule I get this error:

error: method create in class MasjidsRepository_Factory cannot be 
applied to given types;
required: 
Provider<FirebaseFirestore>,Provider<String>,Provider<Masjid>
found:AppModule_ProvideFirestoreDatabaseFactory,HomeModule_ProvideMasjidFactory
reason: actual and formal argument lists differ in length
1

1 Answers

0
votes

I found the problem, the repository is a dep for the viewModel which is by mistake was placed in the HomeScope, so I was capable of using deps from the ActivityModule and any scope above(AppScope).

The mistake is I placed the ViewModelModule of the fragments inside the Subcomponent of the Activity, just moved each fragment ViewModelModule to its subcomponent and it worked.