user1202032
user1202032

Reputation: 1479

Android dagger2 module cannot be injected into other module

Im trying to learn how to use dagger2. Are you supposed to make a component for every single module you have (and then combine components in "super-components")?

I have 2 modules which work, and who used to have individual components. Then i added an additional module (no component), and in the new module my @Inject does not appear to work.

How can i make it so my AppModule can be injected into my new GyroModule?

My new "Gyro" module:

@Module
public class GyroModule implements SensorEventListener {
@Inject AppModule _appModule;  // NULL

private SensorEvent _lastReading;
private SensorManager _sensorManager;
private Sensor _gyro;

@Inject
public GyroModule() {
    initialize();
}

@Provides
@Singleton
public GyroModule provideGyroModule() {
    return this;
}

My MainActivity:

public class MainActivity extends LocationAwareActivity {
    @Inject PointOfInterestModule pointOfInterestModule; // OK
    @Inject LocationModule locationModule;               // OK

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ((AllTheLocateApplication) getApplication()).getAppComponent().inject(this);

        setContentView(R.layout.activity_main);

        Intent intent = new Intent(this, AugmentedActivity.class);
        startActivity(intent);
    }
}

My "god" component (and only component in the app):

@Singleton
@Component(modules={AppModule.class,
        PointOfInterestModule.class,
        LocationModule.class,
        GyroModule.class})
public interface IAppComponent {
    void inject(AllTheLocateApplication application);
    void inject(MainActivity mainActivity);
    void inject(AugmentedActivity augmentedActivity);

    void inject(AppModule appModule);
    void inject(PointOfInterestModule pointOfInterestModule);
    void inject(LocationModule locationModule);
    void inject(GyroModule gyroModule);
}

My AppModule

@Module
public class AppModule {

    AllTheLocateApplication mApplication;

    public AppModule(AllTheLocateApplication application) {
        mApplication = application;
    }

    public AllTheLocateApplication getApplication() {
        return mApplication;
    }

    @Provides
    @Singleton
    AppModule providesAppModule() {
        return this;
    }
}

Upvotes: 0

Views: 1024

Answers (1)

David Medenjak
David Medenjak

Reputation: 34532

Are you supposed to make a component for every single module you have [...]

No.

[...] (and then combine components in "super-components")?

No.


Modules should be your Plan B and—to phrase it clearly—avoided at all cost unless really necessary. There are 3 reasons why you will need to use them though:

  • a dependency cannot be created with constructor injection,
  • a dependency needs further initializtion at the time of the creation
  • a dependency is implementing an interface, you are providing the implementation

If not at least one of those is true, don't use a module.

Injection

Modules have nothing to do with injection. They don't—and should not—contain your business logic. All they do is provide those objects that can't be accessed or constructor injected. They can't be injected, and don't get injected. If one object depends on another, put it as a parameter in the method. If you don't want to call the constructor yourself, dagger willl just create the module for you, given that there is a no-args constructor.

An initialize() method is not supposed to be part of a module. If you have to supply A and A needs be, it should look like the following:

@Provides
provideA(B b) {
    A a = new A();
    a.setB(b);
    a.doMoreInitializationThatMustBeDoneNow();
    return a;
}

Whether B is supplied from the same module, a different module, the parent component, a component dependency or by constructor injection is not of your concetrn. Modules don't need to know about each other and dagger will just call your method with B. You then just have to return A.


I don't know what you are trying to do with your code sample. Modules are not part of your business logic. They provide dependencies. You should not depend on modules from your business logic. Nor should you include getters, setters, or update any objects. Modules create an object and initialize it. They do not interact with it in any other way.

Play a bit with dagger by creating a single java file. Add some modules. Put in a class that you try to inject with some dependencies. You can just see how things compile (or don't). And maybe try reading some more tutorials about dagger for a better understanding of the core concepts.

Upvotes: 4

Related Questions