Skip to content

Dagger 2 issue overriding single provides annotated method from a module in a library which app uses #268

@qazimusab

Description

@qazimusab

GitHub Project Link

I have made a project on GitHub which is a model of the dagger 2 architecture of my projects actual architecture. This question will be based off of the GitHub project.

I have provided many code snippets in this question, however, it may be easier to just compile the project yourself in Android Studio to understand the problem.

If you check out the code, it won't compile. Go into AppModule.java and comment out both provides methods and it should compile.

The main question is the last line on this post.

https://github.com/qazimusab/Dagger2LibraryProject

Architecture

I have a library which contains all the code needed to make the application. The point of this architecture is that each app I create in the project should be able to use the library and ,through dagger 2, be able to provide different implementations for any single class or activity it wants in it's own module. At this point I only have one application in this sample project which uses the library.

The Problem

With dagger one, I had the same architecture, and in the app specific module (as opposed to the library module), I was able to add a new provides annotated method to override any implementation which was being provided in the any of the library modules as long as

The method was in a module in the app module
The method was annotated with @provides
The method had the same return type as the one you want to override
With Dagger 2, the architecture works when I either don't override any provides or if I do, when I override every single provides in that module and remove that module from the includes from the Application specific module.

For example, in my project, I have an app and a library.

The app has an AppModule; the library has a CatModule to provide a Cat and CatFood, a dog module to provide a Dog and DogFood, and a LibraryModule to provide the activities.

CatModule.java

package com.example.qaziahmed.library.application.modules;

import com.example.qaziahmed.library.classes.Cat; import com.example.qaziahmed.library.classes.CatFood; import com.example.qaziahmed.library.classes.contract.ICat; import com.example.qaziahmed.library.classes.contract.ICatFood;

import javax.inject.Singleton;

import dagger.Module; import dagger.Provides;

/** * Created by qaziahmed on 11/23/15. */ @Module public class CatModule {

@Provides
@Singleton
ICat provideCat() {
    return new Cat();
}

@Provides
ICatFood provideCatFood(){
    return new CatFood();
} }

DogModule.java

package com.example.qaziahmed.library.application.modules;

import com.example.qaziahmed.library.classes.Dog; import com.example.qaziahmed.library.classes.DogFood; import com.example.qaziahmed.library.classes.contract.IDog; import com.example.qaziahmed.library.classes.contract.IDogFood;

import javax.inject.Singleton;

import dagger.Module; import dagger.Provides;

/** * Created by qaziahmed on 11/23/15. */ @Module public class DogModule {

@Provides
@Singleton
IDog provideDog() {
    return new Dog();
}

@Provides
IDogFood provideDogFood(){
    return new DogFood();
}
}

So, in my application module, I want to provide a house cat implementation of ICat instead of a generic cat and an AllNaturalDogFood implementation of IDogFood instead of just regular DogFood, then in my AppModule I add two provides to override those

AppModule.java

package com.example.qaziahmed.dagger2libraryproject.application;

import com.example.qaziahmed.dagger2libraryproject.classes.AllNaturalDogFood; import com.example.qaziahmed.dagger2libraryproject.classes.HouseCat; import com.example.qaziahmed.library.application.modules.CatModule; import com.example.qaziahmed.library.application.modules.DogModule; import com.example.qaziahmed.library.application.modules.LibraryModule; import com.example.qaziahmed.library.classes.contract.ICat; import com.example.qaziahmed.library.classes.contract.IDogFood;

import javax.inject.Singleton;

import dagger.Module; import dagger.Provides;

/** * Created by ogre on 2015-07-12 */ @Module(includes = { LibraryModule.class, DogModule.class, CatModule.class }) public class AppModule {

@Provides
@Singleton
ICat provideHouseCat() {
    return new HouseCat();
}

@Provides
IDogFood provideAllNaturalDogFood(){
    return new AllNaturalDogFood();
} }

Now, when I run this setup, this is the error I get:

Error:com.example.qaziahmed.library.classes.contract.ICat is bound multiple times:
      @Provides @Singleton com.example.qaziahmed.library.classes.contract.ICat com.example.qaziahmed.dagger2libraryproject.application.AppModule.provideHouseCat()
      @Provides @Singleton com.example.qaziahmed.library.classes.contract.ICat com.example.qaziahmed.library.application.modules.CatModule.provideCat()
Error:com.example.qaziahmed.library.classes.contract.IDogFood is bound multiple times:
      @Provides com.example.qaziahmed.library.classes.contract.IDogFood com.example.qaziahmed.dagger2libraryproject.application.AppModule.provideAllNaturalDogFood()
      @Provides com.example.qaziahmed.library.classes.contract.IDogFood com.example.qaziahmed.library.application.modules.DogModule.provideDogFood()

Now, if in AppModule.java, I also add provides annotated methods to provide Cat Food and Provide Dog and then remove CatModule.class and DogModule.class from the includes in App Module then it works.

However, the whole question is how do I override a single provides method in some module in the library without having to override every provides annotated method inside that specific module and then removing that module from the includes in AppModule.java

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions