12

Back when I used RoboGuice, I was able to constructor inject Context into of my classes and RoboGuice would pick the appropriate Context (injects in an Activity would have the Activity context, injects in Application would have the current application context, injects in a Fragment would have the fragment's activity's context, etc...).

Is there a similar method for achieving this with Dagger?

public class Thing {
    @Inject
    public class Thing(Context context){
       // if i'm injected in an Activity, I should be the current activity's context
       // if i'm injected in an Fragment, I should be the fragment's activity context
       // if i'm injected in a Service, I should be the service's context
       // etc...
    }
}
Paul
  • 4,422
  • 5
  • 29
  • 55

1 Answers1

23

Dagger doesn't know about Android. Or anything, really. If you want to inject something, you have to tell Dagger about it.

You can see an example of how to inject a Context in the examples. In this case, a qualifier is used to differentiate the application one from an activity one.

/**
 * Allow the application context to be injected but require that it be annotated with
 * {@link ForApplication @Annotation} to explicitly differentiate it from an activity context.
 */
@Provides @Singleton @ForApplication Context provideApplicationContext() {
  return application;
}

Edit

No, you cannot inject an unqualified type and have the instance of that type change based on the context in which you are performing injection. Dagger requires that the source of a type is known at compile-time and since object graphs are immutable that source cannot be changed.

The only way to do this is to use a factory which allows you to specify the context with which the object will be created.

public final class ThingFactory {
  private final Foo foo;
  private final Bar bar;

  @Inject public ThingFactory(Foo foo, Bar bar) {
    this.foo = foo;
    this.bar = bar;
  }

  public Thing get(Context context) {
    return new Thing(context, foo, bar);
  }
}
Jake Wharton
  • 75,598
  • 23
  • 223
  • 230
  • When I last tried the ForApplication method, I was forced by the compiler to annotate the actual injectable member with ForApplication as well -- right? I edited my question with a bit of sample code. I would have to put the annotation here: public class Thing(ForApplication Context context). But that makes it seem like I would only ever get the application context, is that correct? – Paul May 02 '14 at 21:59
  • The factory method is exactly the kinds of boiler plate code that Dagger is supposed to replace. It's annoying that there's no way to pass arguments to ObjectGraph.get(). – enl8enmentnow Dec 21 '14 at 18:01
  • Actually no it's not. Dagger was never designed to do anything with factories. If you want reduced boilerplate you can try AutoFactory. – Jake Wharton Dec 21 '14 at 20:49