Reputation: 21237
I'm trying to refactor some code that relied upon singleton objects, which I am realizing are problematic in Java. My goal is to create a thread-safe instantiation of my AES cipher class that I can access throughout my app.
Following a couple of tutorials about Guice, I have this very basic scenario:
@Singleton
public class AESCipherService { // service class
@Inject
AESCipherService() {}
public void makeKeys() {
Log.d(Constants.TAG, "aes cipher generating keys");
}
}
This is confusing to me since my service class has no subclasses, but all of the examples that I see are about binding a service super class to one of its subclasses.
public class AppInjectorModule extends AbstractModule {
@Override
protected void configure() {
bind(AESCipherService.class);
}
}
public class MyApplication {
private AESCipherService cipher;
@Inject
public void setCipher(AESCipherService cipher) {
this.cipher = cipher;
}
public void makeKeys() {
cipher.makeKeys();
}
}
And finally, the activity onCreate
where this is all supposed to launch from:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_splash_screen);
Log.d(Constants.TAG, "dependency injection test starting");
Injector injector = Guice.createInjector(new AppInjectorModule());
// EDIT: added this line, but it never prints!
Log.d(Constants.TAG, "injector instantiated");
// instantiates the singleton object ???
MyApplication app = injector.getInstance(MyApplication.class);
app.makeKeys();
}
Unfortunately, the only output that I get is dependency injection test starting
. I am not seeing aes cipher generating keys
, as I am hoping.
Where am I going wrong with dependency injection?
EDIT: I added a few print statements to see where this is failing. It seems that it never returns from instantiating the injector object. Any idea why this is failing? It clearly explains why my service class isn't running.
Upvotes: 2
Views: 356
Reputation: 32343
You are not using Guice idiomatically. The right way to use Guice is to create the injector once at startup, use it to create your initial classes (in this case Activities), and let the injection framework create all your injections down the chain.
Creating the injector is an expensive, slow operation, so you do not want to call it when, say, you click a button; it should happen at application start so users do not notice it.
Since you are developing for Android, consider using Roboguice in order to use Guice properly. See: Using Guice to inject dependencies into an Android activity's constructor
In the meantime, try calling Guice.createInjector
in your activity's constructor, saving it as an instance field, then calling getInstance
in the onCreate
method.
Upvotes: 1
Reputation: 405
You need bind also MyApplication.class
public class AppInjectorModule extends AbstractModule {
@Override
protected void configure() {
bind(AESCipherService.class).in(Singleton.class);
bind(MyApplication.class).in(Singleton.class);
}
}
Upvotes: 0