Adapting own Framework to RobotLegs
I'm just getting my feet wet with RL but I have a bit of a trouble to understand how I should utilize RL to adapt to my own framework. Basically I have some view classes which were Singletons in the earlier version of my framework and I want to map them as Singletons with RL but if I try that the classes are not instantiated by RL and I get a null ref exception thrown. Also, is it possible to map a Context class as a Singleton?
Comments are currently closed for this discussion. You can start a new one.
Keyboard shortcuts
Generic
? | Show this help |
---|---|
ESC | Blurs the current field |
Comment Form
r | Focus the comment reply box |
---|---|
^ + ↩ | Submit the comment |
You can use Command ⌘
instead of Control ^
on Mac
Support Staff 1 Posted by Till Schneidere... on 10 Jun, 2010 03:09 PM
Robotlegs doesn't make using singleton views easy, that's true. But
that's also something you should try to avoid if at all possible.
Without knowing the specifics of your setup, it sounds to me like the
easiest way to adapt your architecture would be to introduce a
singleton view registry with which you can register your views. Then
mediate the "singleton" views as all others but register them with the
registry over which they can be accessed by all interested parties.
Mapping a Context (or whatever else) class as a singleton is as easy as
injector.mapSingleton(Context);
2 Posted by sascha on 10 Jun, 2010 03:43 PM
Thanks a lot for the explanation! If I think about it there's only really one view class that was a Singleton which happens to be a (debug) console class to that logging output is sent. I suppose it wouldn't hurt too much to not map it as a Singleton but instead create a Mediator for it?!
About the Singleton Context ... I have a class named Main which is my Context. I've mapped it with:
injector.mapSingleton(Main);
... inside the Main class' startup() and injected it into a view class that has a mediator mapped to it. Now in the mediator I'm trying to access a property of the Main class (in the view class I can't /shouldn't inject Main if I see that right?) but if I try that I get the following exception:
InjectorError: Injector is missing a rule to handle injection into target [class Main]. Target dependency: flash.display::Sprite, method: constructor, parameter: 1
The Main class constructor has a parameter of type Sprite (which becomes the contextView). Any ideas?
Support Staff 3 Posted by Till Schneidere... on 10 Jun, 2010 05:10 PM
You should create a mediator for that debug console, right. Maybe
create an accompanying DebugConsoleModel which you register the
mediator with or something similar.
The reason for your singleton mapping of Main not working is that the
injector can't construct the singleton instance. That's because it
doesn't know how to supply the dependency your Main class's
constructor has: the Sprite. To make it work, you can do one of two
things:
1. create the instance eagerly in your startup method, supplying the
contextView manually. Then you can use mapValue, resulting in that
same value being returned each time the type Main is required for
injection.
2. change the type your Main class's constructor expects to
DisplayObjectContainer - that's the type by which the contextView is
mapped by default.
4 Posted by sascha on 10 Jun, 2010 05:43 PM
Ok I've tried your second suggestion, changing the constructor argument to type DisplayObjectContainer but instead of the former error I'm now getting a Stack Overflow Exception.
About solution Nr. 1 ... but actually the Main class is already existing. I map it (as mentioned above) to Singleton inside its own startup() method and the view class. This is how my Main class looks:
` public class Main extends Context
{
} `
And here's my view mediator:
` public class ApplicationUIMediator extends Mediator
{
} `
Support Staff 5 Posted by Till Schneidere... on 10 Jun, 2010 05:56 PM
Aha, I didn't understand that Main is extending Context!
In that case, just use
injector.mapValue(Main, this);
6 Posted by sascha on 10 Jun, 2010 06:18 PM
Ok that did it! Even though Main is now not mapped as a Singleton anymore. But I guess I can live with that.
Thanks for your time and help! :)
Support Staff 7 Posted by Joel Hooks on 10 Jun, 2010 08:54 PM
Main is effectively mapped as a context managed Singleton. Unless you override that mapping later, only the one instance is available for injection.
8 Posted by sascha on 11 Jun, 2010 02:59 AM
Good to know that, thanks Joel! I was wondering if Context classes get a special treatment like that.
Support Staff 9 Posted by Till Schneidere... on 11 Jun, 2010 10:13 AM
I'm not sure you're saying that, but just to make sure: Context
doesn't get any special treatment at all. In fact, no other class in
the framework even knows about or ever even gets a reference to the
context - it's just something similar to a main entry point that kicks
things off.
What actually happens is that mapValue causes the injector to always
return that same value for each request. That means that ultimately,
mapValue works the same as mapSingleton does, with the only difference
being that singleton mappings don't create the singleton instance
until it is actually requested for the first time.
10 Posted by sascha on 11 Jun, 2010 12:09 PM
Yes, I didn't want to imply that a Context get's a special treatment as in "being treated as a Singleton". i guess my quote above is misleading.
I got another small question: How do I inject a static class? I have one class which has only static methods and in this class I need access to two other classes which are mapped. I injected these two in the static class as static properties but how do I get RL to map the static class?
Support Staff 11 Posted by Till Schneidere... on 11 Jun, 2010 03:08 PM
You can neither inject into static fields of a class, nor can you map
the class itself to anything but "Class". The first of these you
should not do anyway: Static state should be avoided if in any way
possible at all. The second just doesn't work. For example, "MyClass"
is an instance of the class "Class", so all you could do would be to
use injector.mapValue(Class, MyClass), but I guess that's not what you
imagined.
I would recommend changing your class to not use static state and
methods and inject an instance of it using mapSingleton or mapValue.
If you've got any further questions about this, please open a new
topic, as this is really unrelated to the topic discussed here
earlier. Thus, I'm closing this thread now.