NagRock
NagRock

Reputation: 325

Dagger auto injection

I have 3 classes in my simple project using dagger:

public class MyActivity extends Activity {
    @Inject
    public MyController controller;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        setContentView(R.layout.search);
        super.onCreate(savedInstanceState);
        objectGraph = ObjectGraph.create(new BootstrapModule(this));
        objectGraph.inject(this);
        System.out.println("MyActivity.controller: " + controller);
    }
}

public class MyController {
    @Inject
    public EventDispatcher eventDispatcher;

    public MyController()
    {
        System.out.println("MyController.eventDispatcher: " + eventDispatcher); // THIS IS NULL!
    }
}

@Module(injects = {
        MyActivity.class,
        MyController.class
})
public class BootstrapModule {
    private Context context;

    public BootstrapModule(Context context){
        this.context = context;
    }

    @Provides
    @Singleton
    public EventDispatcher provideEventDispatcher(){
        return new EventDispatcher();
    }

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

Now my problem is that on MyActivity controller is created by dagger after objectGraph.inject(this) method call. But in MyController eventDispatcher is not created. Do I have call again from Activity objectGraph.inject(controller) to get created EventDispatcher by dagger? Should it be done automaticly?

Upvotes: 0

Views: 1146

Answers (2)

zhaocong
zhaocong

Reputation: 334

Injection never happens automatically but follows the hints given by @Inject. You can either inject via constructor or inject manually and either way has its own advantages and disadvantages. Personally I prefer manual injection since it offers more control.

Inject via constructor

Pro

  • the dependency will be resolved automatically even deep in hierarchy
  • no need to declare this injected rule via component

Con

  • You cannot control when the injection happens

Manual injection

Pro

  • control the life cycle and may inject many times with different components

Cons

  • need to write extra code to make it happen

Upvotes: 1

Miguel
Miguel

Reputation: 20123

Field Injection is done after the constructor from MyController is completed. Therefore during the constructor execution the EventDispatcher instance hasn't yet been set. If you breakpoint your code just after this line "objectGraph.inject(this);" in your onCreate you'll see that the EventDispatcher as been set.

To solve this issue you need to switch to Constructor Injection. You can accomplish this by moving your @Inject from the EventDispatcher Field to your MyController Constructor and add the EventDispatcher as a dependency like so.

public class MyController {

    public EventDispatcher eventDispatcher;

    @Inject
    public MyController(EventDispatcher eventDispatcher)
    {
        this.eventDispatcher = eventDispatcher;
        System.out.println("MyController.eventDispatcher: " + eventDispatcher); // THIS WON'T BE NULL!
    }
}

Upvotes: 2

Related Questions