Dagger: The correct way to define an injection class that takes a context in its constructor
I want to use dagger (dagger v1 by Square) to create a singleton class whose constructor requires context as an argument. Then I want to inject this singleton class into my MainActivity. What are the correct steps to determine this?
I tried to do this:
SingletonClass:
@Module(
injects = {MainActivity.class}
)
@Singleton
public class SingletonClass {
...
@Inject
SingletonClass(Context ctx) {}
}
to which I get the error:
no injectable members on android.content.Context
I understand that the SingletonClass has to get its context from somewhere to be injected, but since I no longer "call" it in the traditional sense, but instead I inject it like this in MainActivity at the class level:
@Inject SingletonClass singletonClass;
how should I pass this context?
Here are the additional files I created for the dagger (two of which I saw in the official examples):
AndroidModule:
@Module(library = true, injects = MainActivity.class)
public class AndroidModule {
private final Context context;
public AndroidModule(Context context) {
this.context = context;
}
/**
* Allow the application context to be injected but require that it be
* annotated with to explicitly
* differentiate it from an activity context.
*/
@Provides
@Singleton
@ForApplication
Context provideApplicationContext() {
return context;
}
}
App.class (for extending my app):
public class App extends Application {
private static final String TAG = App.class.getSimpleName();
private static App instance;
public MainActivity mainActivity;
private static Context context;
private ObjectGraph objectGraph;
public void onCreate() {
super.onCreate();
instance = this;
context = getApplicationContext();
objectGraph = ObjectGraph.create(getModules().toArray());
}
public static App getInstance() {
return instance;
}
public static Context getContext() { return context; }
protected List<Object> getModules() {
return Arrays.asList(new AndroidModule(this), new App());
}
public void inject(Object object) {
objectGraph.inject(object);
}
}
ApplicationApplication class:
import java.lang.annotation.Retention;
import javax.inject.Qualifier;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
@Qualifier @Retention(RUNTIME)
public @interface ForApplication {
}
source to share
You need to add a qualifier @ForApplication
to your parameter Context
in the constructor SingletonClass
.
The dagger is now looking Context
for injection, but only has @ForApplication Context
that is a mismatch.
@Singleton
public class SingletonClass {
@Inject
SingletonClass(@ForApplication Context ctx) {
}
}
Now you can also get rid of the line library = true
in AndroidModule
which you probably added because Dagger warned you that it was @ForApplication Context
not used (don't ignore those warnings!).
Also, and it might just be a copy-paste error, this SingletonClass
one shouldn't contain annotation @Module
.
source to share