How to declare dependencies

2019-07-15 08:18发布

问题:

I'm studying Dagger 2 so I would like to understand some basic things. I have the following code:

@Module
public class MainModule {

@Provides
public Presenter provideMainActivityPresenter(Model model){
    return new MainPresenter(model);

}

@Provides
public Model provideMainModel(){
    return new MainModel();
 }
}

and my MainPresenter class looks like this:

public class MainPresenter implements Presenter {

@Nullable
private ViewImpl view;
private Model model;



public MainPresenter(Model model) {
    this.model = model;
}

@Override
public void setView(ViewImpl view) {
    this.view = view;
  }
 }

Instead of the above code, could I do the following?

public class MainPresenter implements Presenter {

@Nullable
private ViewImpl view;

@Inject
Model model;


@Override
public void setView(ViewImpl view) {
    this.view = view;
 }
}

Because the MainPresenter depends on the Model and it is not @Nullable.
Or this is wrong?

I don't understand when I should put a dependency as a constructor argument, or when I should use @Inject

回答1:

You have basically 3 ways to use Dagger

  • Constructor injection
  • Field injection
  • Providing it from a module yourself

(There is also method injection which calls a method after creating your object)


The following is using a module that provides your class. While not wrong, this is the most overhead to write and maintain. You create the object by passing in the requested dependencies and return it:

// in a module

@Provides
public Presenter provideMainActivityPresenter(Model model){
  // you request model and pass it to the constructor yourself
  return new MainPresenter(model);
}

This should be used with things that require additional setup, like Gson, OkHttp, or Retrofit so that you can create the object in one place with the required dependencies.


The following would be used to inject objects where you don't have access or don't want to use the constructo. You annotate the field and register a method at the component to inject your object:

@Component class SomeComponent {
  void injectPresenter(MainPresenter presenter);
}

public class MainPresenter implements Presenter {

  // it's not annotated by @Inject, so it will be ignored
  @Nullable
  private ViewImpl view; 

  // will be field injected by calling Component.injectPresenter(presenter)
  @Inject
  Model model;

  // other methods, etc
}

This will also provide you with overhead to register all your classes at a presenter and should be used when you can't use the constructor, like Activities, Fragments, or with Services. That's why all those Dagger samples have those onCreate() { DaggerComponent.inject(this); } methods to inject parts of the Android framework.


Most importantly you can use Constructor Injection. You annotate the constructor with @Inject and let Dagger find out how to create it.

public class MainPresenter implements Presenter {

  // not assigned by constructor
  @Nullable
  private ViewImpl view;

  // assigned in the constructor which gets called by dagger and the dependency is passed in
  private Model model;

  // dagger will call the constructor and pass in the Model
  @Inject 
  public MainPresenter(Model model) {
    this.model = model;
  }
}

This only requires you to annotated your class constructor and Dagger will know how to handle it, given that all the dependencies (constructor arguments, Model in this example) can be provided.


All of the methods mentioned above will create an object and can / should be used in different circumstances.

All of those methods either pass the dependencies to the constructor, or inject @Inject annotated fields directly. Dependencies should thuse be in the constructor or annotated by @Inject so that Dagger knows about them.

I also wrote a blog post about the basic usage of Dagger 2 with some further details.