I'm using Dagger to inject dependencies into an Android application, and I stumbled on an issue which I am not entirely sure how to resolve in a clean way.
What I'm a trying to achieve is to instanciate helpers and inject them within my activity, and have these helpers contain injected members too.
What works
The activity where my helper is being injected:
public class MyActivity extends Activity {
@Inject SampleHelper helper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
((MyApplication) getApplication()).inject(this);
Log.i("debug", "helper = " + helper);
Log.i("debug", "helper context = " + helper.context);
}
}
The application creating the object graph:
public class MyApplication extends Application {
private ObjectGraph graph;
@Override
public void onCreate() {
super.onCreate();
graph = ObjectGraph.create(getModules());
}
private Object[] getModules() {
return new Object[] { new MyModule(this) };
}
public void inject(Object target) {
graph.inject(target);
}
}
The injection works perfectly when I instanciate directly a SampleHelper class, which in its turn receives an injected application context:
@Singleton
public class SampleHelper {
@Inject public Context context;
@Inject
public SampleHelper() {}
}
With the following module:
@Module(
injects = { MyActivity.class },
complete = false,
library = true
)
public class MyModule {
private final MyApplication application;
public MyModule(MyApplication application) {
this.application = application;
}
@Provides @Singleton Context provideApplicationContext() {
return application;
}
}
What doesn't work
However, when I separate the helper interface from its implementation:
public interface SampleHelper {
}
@Singleton
public class SampleHelperImpl implements SampleHelper {
@Inject public Context context;
@Inject
public SampleHelperImpl() {}
}
And add this to the dagger module:
public class MyModule {
...
// added this method
@Provides @Singleton public SampleHelper provideSampleHelper() {
return new SampleHelperImpl();
}
...
}
The context doesn't get injected in my SampleHelperImpl, as I would have expected. Now, I guess this is due to SampleHelperImpl being instanciated through direct constructor call rather that injection-initiated constructor call, because MyModule#provideApplicationContext() doesn't even get called, so my guess is I'm missing something about Dagger (which is likely, as my previous DI experiences only included Spring).
Any idea about how to have my context injected in my injected helper implementation, in a "clean Dagger" way?
Thanks a lot!
This is a fairly old question but I think what you want is this:
@Provides @Singleton public SampleHelper provideSampleHelper(SampleHelperImpl impl) {
return impl;
}
This way Dagger will create your SampleHelperImpl
and therefore inject it.
In case anyone is interested, when implementing an @Provides method in a dagger module, you can get dagger-handled objects instances like that:
@Provides @Singleton public SampleHelper provideSampleHelper(Context context) {
SampleHelper helper = new SampleHelperImpl();
helper.setContext(context);
return helper;
}
This works, but I still feel it's a bit clumsy, as I have to call my helpers setters explicitly (typically what you want to get rid of with injection).
(I'll wait a bit in case someone comes with a better solution)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With