Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dagger2 error: Cannot provide without @Inject constructor

i'm totally new to Dagger 2 and have a small problem. Hope you can help me :) I have the following classes in my android project

  1. App
  2. AppComponent
  3. AppModule
  4. MainActivity
  5. MainComponent
  6. MainModule
  7. IntentStarter

At rebuilding/compiling i get the error

Error:(15, 10) error: xyz.IntentStarter cannot be provided without an @Inject constructor or from an @Provides- or @Produces-annotated method.
xyz..MainActivity.intentStarter
[injected field of type: xyz..IntentStarter intentStarter]

I tried a lot of variants but without success... I tried it with a constructor in the IntentStarter class.. without constructor... :/ Now some code...

// AppComponent.class
@Singleton
@Component(modules = {AppModule.class})
public interface AppComponent {
// Empty...
}

...

// AppModule.class
@Singleton
@Module
public class AppModule {

    Application application;
    Context context;


    public AppModule(Application app) {
        this.application = app;
        this.context = app.getApplicationContext();
    }


    @Provides
    public Application provideApplication() {
        return application;
    }

    @Provides
    public Context provideContext() {
        return context;
    }

    @Provides
    public EventBus provideEventBus() {
        return EventBus.getDefault();
    }

    @Provides
    public IntentStarter provideIntentStarter() {
        return new IntentStarter();
    }
}

...

// App.class
public class App extends Application {

    public AppComponent appComponent;

    public AppComponent getAppComponent() {
        return appComponent;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        appComponent = DaggerAppComponent.builder()
            .appModule(new AppModule(this))
            .build();
    }
}

...

//MainAcitivty.class
public class MainActivity extends MosbyActivity {

    @Inject
    IntentStarter intentStarter;

    MainActivityComponent component;

    @Override
    protected void injectDependencies() {
        component = DaggerMainActivityComponent.builder()
                .appComponent(((App) getApplication()).getAppComponent())
                .build();
        component.inject(this);
    }
}

...

//MainActivityComponent.class
@ActivityScope
@Component(dependencies = {AppComponent.class})
public interface MainActivityComponent {
    void inject(MainActivity mainActivity);
}

...

// MainActivityModule
@Module
public class MainActivityModule {

}

...

//IntentStarter
public class IntentStarter {

    @Inject
    Context context;

}
like image 999
Tobias Avatar asked Sep 27 '22 22:09

Tobias


1 Answers

First thing first, as I said, your provision methods are missing from your components. For example,

 @Component(modules={AppModule.class})
 @Singleton
 public interface AppComponent {
        Context context();
        IntentStarter intentStarter();
 }

 @Component(dependencies={AppComponent.class}), modules={MainActivityModule.class})
 @ActivityScope
 public interface MainActivityComponent extends AppComponent {
        //other provision methods
 }

And you are making a mistake with field injection, your IntentStarter needs to either call appComponent.inject(this) or needs to get your context in a constructor parameter.

Also, I think the @Provides annotated method needs the @Singleton scope to get a scoped provider, and marking the module itself doesn't actually do anything.

So, to be specific,

@Singleton
@Component(modules = {AppModule.class})
    public interface AppComponent {
    Application application();
    Context provideContext();
    EventBus provideEventBus();
    IntentStarter provideIntentStarter();
}

@Module
public class AppModule {
    Application application;
    Context context;

    public AppModule(Application app) {
        this.application = app;
        this.context = app.getApplicationContext();
    }


    @Provides
    public Application provideApplication() {
        return application;
    }

    @Provides
    public Context provideContext() {
        return context;
    }

    @Provides
    @Singleton
    public EventBus provideEventBus() {
        return EventBus.getDefault();
    }

    @Provides
    @Singleton
    public IntentStarter provideIntentStarter(Context context) {
        return new IntentStarter(context);
    }
}

@ActivityScope
@Component(dependencies = {AppComponent.class}, modules={MainActivityModule.class})
public interface MainActivityComponent extends AppComponent {
    void inject(MainActivity mainActivity);
}

public class IntentStarter {    
    private Context context;

    public IntentStarter(Context context) {
        this.context = context;
    }   
}
like image 172
EpicPandaForce Avatar answered Sep 30 '22 08:09

EpicPandaForce