Reputation: 6060
I'm using @ContextSingleton
to mark singletons that depend on the injection on contexts. From looking at RoboGuice sources and from my own tests it seems however as if it makes a difference between the Application
context and different activity contexts. This makes perfectly sense, just that it is - at least for me - problematic when I'm using it together with the event management facility like this:
@ContextSingleton
public class Service {
@Inject
private Context context;
public void doSomething(@Observes MyEvent ev) {
...
}
}
Though the service is defined as singleton, no instance of it seems to be created until it is first injected somewhere, apparently through lazy-loading. So fireing a MyEvent
does not make the listener call upon. We thought then we could "manually" eager-load the classes beforehand in our application like
RoboGuice.get(context).getInstance(Service.class);
and therefor get the listeners registered, but this only worked properly when executed within the Activity that later also injected the EventManager
to fire the event, but not the application.
So, in an ideal world I'd expect that I could tell RoboGuice to which context it should bind a singleton, much like this
@ContextSingleton(MyApplication.class)
public class Service {
...
}
but apparently this is not possible.
What am I missing?
Upvotes: 3
Views: 3283
Reputation: 38168
@JRaymond is right. An instance of a RoboGuice Event listener can't listen to events in more than one context.
But this can be easily solved. Don't make your singleton listen to events directly. Each activity can listen to its own events and then put the singletong in a given state :
public class MyActivity extends RoboActivity {
@Inject
private InsideAppManager mInsideAppManager;
public void onHandleResumeEvent( @Observes OnResumeEvent onStartEvent ) {
mInsideAppManager.setInsideApp(true);
}
public void onHandlePauseEvent( @Observes OnPauseEvent onStopEvent ) {
mInsideAppManager.setInsideApp(false);
}
}
And your singleton :
@Singleton
public class InsideAppManager {
private boolean isInsideApp;
public boolean isInsideApp() {
return isInsideApp;
}
public void setInsideApp(boolean isInsideApp) {
this.isInsideApp = isInsideApp;
}
}
Upvotes: 2
Reputation: 11782
I think You're missing that events don't propogate across contexts and are context specific - see the "Things to be aware of" section in the (old, but still valid) events documentation. So even if your singleton is loaded in the application context, it can't be made aware of events occurring within the context of each activity. I assume they had a good reason for doing it that way, but Maybe if you subclass Application
you can inject an EventManager
there to be globally accessible.
I haven't tried it so I'm not sure it will work, and at any rate at that point you'd have to be injecting events into a different EventManager, so you might be better off defining an interface for this singleton and work with it that way, since events won't propogate the way you'd like them to.
Upvotes: 2