How to call a remoteObject method that is outside of my TitleWindow component on Flex? - actionscript-3

I have a TitleWindow component. It allows me to save some data provided through 3 TextInput.
That data "fills" a DropDownList which is in another TitleWindow component, not inside the original one.
How can I call the remoteObject method that fills (or refresh) my DropDownList?
Any ideas will be appreciated!

You can simply use a Singleton as a model if you'd like, this will allow you to share data, but beware keep data only that needs to be shared in here or it will just become a global nightmare.
Using a singleton means you'll have a class that you can only ever have one instance of. If you put properties in that class any time you reference it it will be the same memory throughout the application execution.
http://blog.pixelbreaker.com/actionscript-3-0/as30-better-singletons
Marking the singleton class or individual properties as Bindable will make it so you can watch for the changes and call a function.
http://livedocs.adobe.com/flex/3/html/help.html?content=databinding_8.html
Putting this together you have something like this:
[Singleton.as]
package
{
[Bindable]
public class Singleton
{
public var myListData:Array;
public static var instance:Singleton;
public static function getInstance():Singleton
{
if( instance == null ) instance = new Singleton( new SingletonEnforcer() );
return instance;
}
public function Singleton( pvt:SingletonEnforcer )
{
// init class
}
}
}
internal class SingletonEnforcer{}
Somewhere else you want to get a handle on this
[MyTitleWindow.as]
var instance:Singleton = Singleton.getInstance();
instance.myListData = [1,2,3];
[MyTitleWindowWithAList]
var instance:Singleton = Singleton.getInstance();
BindingUtils.bindSetter(funcUpdateList, instance, "myListData");
private function funcUpdateList(data:Object)
{
myList.dataProvider = data as Array;
}
Another option is to create an event that carries your data payload, dispatch that event from the first title window, and capture it, the problem with this is you have to register the listeners on the PopUpManager or SystemManager I believe because the TitleWindow's aren't direct children of the Application I believe.

Singletons are a bad idea and you should not get in the habit of using them. Instead, just dispatch an event from the View and catch it from something else that has access to your Service object.
Note that your Service should not be part and parcel of any View--the responsibility of a View is displaying data and capturing requests from the user to change the data, not communicating with a server.
For examples of an application written with this pattern in mind, check out
[Refactoring with Mate] (http://www.developria.com/2010/05/refactoring-with-mate.html) - The example has View source enabled
The same application done with RobotLegs - again, View Source is enabled.
Note that these are written against some popular frameworks, but they are written in such a way that you can easily replace that framework code with something else, even your own code.
For reference, here is the naiive implementation, where the service layer is being called directly in the Views. You couldn't call a different service without changing the Views, though the use of the static service means you could use it from elsewhere.
That static usage survived into the later examples, though today I would never write something depending on a globally accessible object. In part this is because I discovered Test Driven Development, and it is impossible to replace the "real" static object with an object that lets you isolate what you are testing. However, the fact that most of the code in the 2 "better" examples is insulated from that static object means that it is trivial to replace it with one that is provided some other way.
The lesson here is if you're going to use static, global objects, lock them away behind as much abstraction as you can. But avoid them if you're at all interested in best practice. Note that a Singleton is a static global object of the worst kind.

Related

JavaFX FXML Parameter passing from Controller A to B and back

I want to create a controller based JavaFX GUI consisting of multiple controllers.
The task I can't accomplish is to pass parameters from one Scene to another AND back.
Or in other words:
The MainController loads SubController's fxml, passes an object to SubController, switches the scene. There shall not be two open windows.
After it's work is done, the SubController shall then switch the scene back to the MainController and pass some object back.
This is where I fail.
This question is very similar to this one but still unanswered. Passing Parameters JavaFX FXML
It was also mentioned in the comments:
"This work when you pass parameter from first controller to second but how to pass parameter from second to first controller,i mean after first.fxml was loaded.
– Xlint Xms Sep 18 '17 at 23:15"
I used the first approach in the top answer of that thread.
Does anyone have a clue how to achieve this without external libs?
There are numerous ways to do this.
Here is one solution, which passes a Consumer to another controller. The other controller can invoke the consumer to accept the result once it has completed its work. The sample is based on the example code from an answer to the question that you linked.
public Stage showCustomerDialog(Customer customer) {
FXMLLoader loader = new FXMLLoader(
getClass().getResource(
"customerDialog.fxml"
)
);
Stage stage = new Stage(StageStyle.DECORATED);
stage.setScene(
new Scene(
(Pane) loader.load()
)
);
Consumer<CustomerInteractionResult> onComplete = result -> {
// update main screen based upon result.
};
CustomerDialogController controller =
loader.<CustomerDialogController>getController();
controller.initData(customer, onComplete);
stage.show();
return stage;
}
...
class CustomerDialogController() {
#FXML private Label customerName;
private Consumer<CustomerInteractionResult> onComplete
void initialize() {}
void initData(Customer customer, Consumer<CustomerInteractionResult> onComplete) {
customerName.setText(customer.getName());
this.onComplete = onComplete;
}
#FXML
void onSomeInteractionLikeCloseDialog(ActionEvent event) {
onComplete.accept(new CustomerInteractionResult(someDataGatheredByDialog));
}
}
Another way to do this is to add a result property to the controller of the dialog screen and interested invokers could listen to or retrieve the result property. A result property is how the in-built JavaFX dialogs work, so you would be essentially imitating some of that functionality.
If you have a lot of this passing back and forth stuff going on, a shared dependency injection model based on something like Gluon Ignite, might assist you.
I've used AfterBurner.fx for dependency injection, which is very slick and powerful as long as you follow the conventions. It's not necessarily an external lib if you just copy the 3 classes into your structure. Although you do need the javax Inject jar, so I guess it is an eternal reference.
Alternately, if you have a central "screen" from which most of your application branches out you could use property binding probably within a singleton pattern. There are some good articles on using singleton in JavaFX, like this one. I did that for a small application that works really great, but defining all of those bindings can get out of hand if there are a lot of properties.
To pass data back, the best approach is probably to fire custom Events, which the parent controller subscribes to with Node::addEventHandler. See How to emit and handle custom events? for context.
In complex cases when the two controllers have no reference to each other, a Event Bus as #jewelsea mentioned is the superior option.
For overall architecture, this Reddit comment provides some good detail: https://www.reddit.com/r/java/comments/7c4vhv/are_there_any_canonical_javafx_design_patterns/dpnsedh/

AS3: Create static variables in registry from external list

I have an application which will be using large numbers of assets. In order to better handle that I chose to use a registry to hold all the assets so they are accessible across the entire application:
package
{
public class SpriteRegistry
{
public static var SPRITENAME = "link to image file";
public function SpriteRegistry()
{
}
}
}
What I would like to do is create an XML document and list off the file name and link so that when the application starts, this registry creates its variables which are freely accessible from that list without me needing to hard code any content directly into it.
Specifically what I need to know is how to get the "public static" effect or how to get an equivalent effect for variables that I CAN dynamically produce.
More info:
I am using a function that loads a sprite texture into a sprite object based on a string variable called mouseAttribute:
loadGraphic(SpriteRegistry[currentAttribute+"Texture"]);
Basically it's like a painting program but for a level editor for a video game.
The problem is that I'm eventually going to have 100+ sprites that I need to application to load and then I need the loadGraphic function to still be able to point effectively to the target sprite.
The library I'm using also needs me to embed the source into a class before I can pull it into the sprite object:
[Embed(source = "/Images/GridTile.png")]
public static var gridTileTexture:Class;
The reason I'm trying to avoid an array is because it means that I will have to search through an array of 100+ objects to find one sprite every time I click a single grid on the editor. That is going to chug.
It's very simple - just use a static function, which will return the XML. So you will need to load the XML file somehow (you decide where, but your registry class should have reference to it). Something similar to this:
private static var _xml:XML;
public static function initialize(xml:XML):void {
_xml = xml;
}
public static function getXML():XML {
return _xml;
}
So you will use it like that:
SpriteRegistry.initialize(loadedXML); // done only once when you initialize your app
trace(SpriteRegistry.getXML().someValue); // someValue is directly from the XML
It's a common used strategy and most of the times you would have something like an app initializer - something to load and instantiate all the things, then pass them to some registries that keep them stored for faster and global usage.
Edit:
After reading your further comments, I can't see any big change - everything would be ok with this resolution.
If you are worried about the 'need to search through array' - just do it as an object! This way you will be able to directly access the proper one using a key exactly like you pointed:
private static var _registry:Object;
public static function initialize(xml:XML):void {
// loop through xml and insert items
_registry[key] = resource;
}
public static function getResource(id):Object {
return _registry[id];
}
This way you can use it like:
SpriteRegistry.getResource(currentAttribute+"Texture");
My personal opinion is that you should avoid statics wherever possible. Instead, you should just create a single instance and provide it through dependency injection where needed.
If you were to go with that approach, you could do something like:
public function getSprite(spriteName:String):Class{
return this[spriteName];
}
or
public function getSprite(spriteName:String):Class{
return yourDictionaryOrObject[spriteName];//I'd implement it this way
}
Otherwise you could go with something like:
public static function getSprite(spriteName):Class{
return ThisHonkingBigUnnchangeableClassname[spriteName];
}
What I would not do is create a Dictionary in a static-only Class, because you're almost inevitably going to wind up with global mutable state.
Discussion, per request
Why would you want to create an instance and pass it, rather than hard-code a reference to a specific Class? A lot of the answers are covered in the global mutable state link above, but here are some that are specific to this kind of problem:
Flexibility. Say you build everything with the idea that you'd only have one set of resources being used in parallel, then you discover you need more than one--for example you might need one for color blind users, or multiple languages, or thumbnails vs. full-sized. If you hard-code to a static, then you'll have to go in every place that was hard-coded and make some sort of change to use a different set, whereas if you use DI, you just supply a different instance loaded with different resources, and done.
Testability. This is actually covered in the link, but I think it bears pulling out. If you want to run a quick test on something that needs a resource, you have to have that static "thing" and you can't change anything about it. It then becomes very difficult to know if the thing you're actually testing is working or if it just appears to be working based on the current implementation of the "thing."
Resource use: everything about an all-static Class exists from the time the swf loads to the time it unloads. Instances only exist from when you instantiate them until they are garbage collected. This can be especially important with resource files that contain embedded assets.
I think the important thing about Frameworks is to realize how they work. The major ones used in ActionScript work the same way, which is they have a central event dispatcher (event bus) that anything loaded to the framework can get a reference to by declaring an interest in it by asking for it to be injected. Additionally, they watch the stage for an event that says that something has been added (in RL it's ADDED_TO_STAGE, whereas in Mate it's the Flex event CREATION_COMPLETE). Once you understand these principles, you can actually apply them yourself with a very light hand without necessarily needing everything that comes along with a framework.
TL;DR
I usually try to avoid answering questions that weren't asked, but in this case I think it would be helpful to discuss an entirely different approach to this problem. At root, the solution comes down not to injecting an entire resource instance, but instead just injecting the resource that's needed.
I don't know what the OP's code is like, but this solution should be general enough that it would work to pass named BitmapDatas to anything that implements our Interface that is capable of dispatching against whatever IEventDispatcher we set as the eventBus (this could be the stage, a particular DisplayObject, or an EventDispatcher that is created just for the purpose.
Note that this code is strikingly similar to code I have in production ;).
public class ResourceManager {
//this can be loaded dynamically, or you can create subclasses that fill the registry
//with embedded Classes in the constructor
protected var registry:Dictionary = new Dictionary();
protected var _eventBus:IeventDispatcher;
public function registerResource(resourceName:String, resourceClass:Class):void {
var bitmap:BitmapData = new resourceClass as BitmapData;
if (resourceClass) {
registry[resourceName] = bitmap;
} else {
trace('Class didn\'t make a BitmapData');
}
}
public function getResource(resourceName:String):BitmapData {
var resource:BitmapData = registry[resourceName];
if (!resource) trace('there was no resource registered for', resourceName);
}
public function get eventBus():IEventDispatcher {
return _eventBus;
}
public function set eventBus(value:IEventDispatcher):void {
if (value != _eventBus){
if (_eventBus) {
_eventBus.removeEventListener(YourCustomEvent.GET_RESOURCE, provideResource);
}
_eventBus = value;
if (_eventBus) {
_eventBus.addEventListener(YourCustomEvent.GET_RESOURCE, provideResource);
}
}
}
protected function provideResource(e:YourCustomEvent):void {
var client:IBitmapResourceClient = e.target as IBitmapResourceClient;
if (client) {
client.resource = getResource(e.resourceName);//your custom event has a resourceName property that you populated when you dispatched the event.
}
}
}
Note that I didn't provide the Interface or the custom event or an example implementation of the Interface due to the fact I am on my lunch break, but if anyone needs that to understand the code please post back and I'll fill that in.

Is there a way to access entry point class object from other classes of the app?

Just wonder if I can reference entry point object from any place in the app? Is it maybe assigned to some global object, like stage is for example?
Currently I use static methods and variables, but this breaks encapsulation.
If someObject is in display list, then you have a someObject.root reference which is what you are looking for. If you remove someObject from display list, you loose that reference.
My answer is no, there is no direct way to access entry object, and there shouldn't be: that's what incapsulation is about. Accessing something globally is pretty much AS1 way. When you access main instance by implicitly referencing MainClass, you make parts of your application tightly coupled, which is generally bad.
However, if you do need to have it, you may choose from several options.
Use static var: MainClass.instance
Use singletone-like access through MainClass.getInstance()
Create a package-level variable or a package level getter method
I would choose the latter.
package com.smth.application
{
public var mainObject:MainClass;
}
// in main app
package com.smth.application
{
public function MainClass()
{
mainObject = this;
}
}
It may look somewhat similar to static acces, but I think this way your code will retain some flexibility.
stage is a reference to the top level of your application, which you can access though any display object that is on the display tree as myDisplayObject.stage. When using a custom document class, it will be the first child (index 0) of stage, unless you manually force something else into the 0 index as Bakapii says.

AS3 How do you access an instance of a class from anywhere?

I currently pass a reference to my model through the constructor to any class that needs it in my simple mvc pattern, this can get annoying at times when it starts to go deeper.
How do Classes such as LoadMax allow you from anywhere to simple import the class, and do something like addChild(LoaderMax.getContent("bg"));? Replicating this should surely be a good way to have my model work, without the complexity of big frameworks?
Statics are your friend
As previous answers have noted, TweenLite/Max etc. makes heavy use of static members to get work done. This is exactly like the Math class, for example, and can be a very convenient design pattern. You have global access to the class, and that can definitely alleviate the issue of getting access to variables through deeply nested classes.
Statics are the enemy
Statics, however, bring certain problems to the table. Most importantly, they tend to reduce flexibility and modularity of classes through the often unnecessary addition of tightly coupled relationships. It's a bit like pouring concrete over your application. It does work, but changing behavior becomes difficult as project features change.
Static members != instance members
Note, very clearly, that a static member "belongs" to the class itself, and not an instance of that class. Static members have no access to instance members. This causes troubles when you want to mix these members up in logic. You tend to have to make everything static (the so-called "static-cling" effect). Static patterns are often argued to be argued to be "anti" object-oriented, for precisely this reason. Once you build a structure on a static pattern you tend to lose many of the principles that makes OOD powerful.
In small does, they're pretty nice
That all being said - TweenLite is a great example of a static pattern that is totally appropriate - its a utility package, one that logic is not dependent on. And that should probably be how you leverage statics, too.
To reduce reliance on statics, or even global vars, it does often mean writing more code, but the flexibility in app structure gained is often quite worth it. #Marty_Wallace has a pretty good solution imo.
Demeter and the Paperboy
Finally, I'll just mention the Law of Demeter, or the Principle of Least Knowledge, and the related Paperboy and the Wallet example, which is often pointed to in discussions of statics:
Each unit should have only limited knowledge about other units: only
units "closely" related to the current
unit.
Each unit should only talk to its friends; don't talk to strangers.
Only talk to your immediate friends.
Hopefully that sheds a little bit of light on a fairly complicated and not-often obvious issue.
This is done using the static namespace, however I discourage the use of this.
package
{
public class Main
{
public static function sayHell():void
{
trace("hello!");
}
}
}
You can now call sayHello() like this from anywhere in the application (assuming you've imported the class).
Main.sayHello();
Another thing you can do (to make the entire class accessible from within the application) is create a static property that refers to the class itself:
package
{
public class Something
{
public static var instance:Something;
public function Something()
{
instance = this;
}
public function someFunction():void
{
trace('hello!');
}
}
}
Which you can now use like so:
Something.instance.someFunction();
The only thing to note here is that you need to create an instance of Something for this to work to call the constructor and define instance.
What I would do
Create a base class for all objects in your application
Create a manager class that takes care of these objects
Create a setter within your base class to define the manager
Here's an example:
Base
package
{
public class Base extends Object
{
private var _manager:Manager;
public function set manager(m:Manager):void
{
_manager = m;
init();
}
protected function init():void
{
manager.someFunction();
}
public function get manager():Manager{ return _manager; }
}
}
Manager
package
{
public class Manager extends Object
{
public function someFunction():void
{
trace('hello!');
}
}
}
Now anything that extends Base will have access to anything held in Manager via the manager getter property. All you need to do is make sure you define the manager, which is easily achieved from within anything that extends Base like so:
var something:SomeExtendingClass = new SomeExtendingClass();
something.manager = manager;
The example you gave is just a static method, but to answer your question about a global instance of a class:
package myPackage
{
public var globalVariable:MyClass = new MyClass();
}
You can access it with:
import myPackage.globalVariable;
trace(globalVariable);
I think you have to rethink in which way you want to name your classes.
You can instantiate whatever class you want, at run-time, but to access a instance by name, you have to make changes in your structure. For example, the getContent() function you mentioned in LoaderMax, all it does is to search in an array for the given loader that matchs the name, among other things. You can read the name variable comment for a description.
A name that you use to identify the loader instance. This name can be fed to the getLoader() or getContent() methods or traced at any time. Each loader's name should be unique. If you don't define one, a unique name will be created automatically, like "loader21".
So in this system, you have to name every single member (loaders in this case) if you want to be able to search them. Because if I call getClassInstance("myinstance"), what is "myinstance" representing? Where should I name it?
That said, if you want to do it for DisplayObjects only, you can use getChildByName. But again, you have to name every DisplayObject (just set the name variable).
Hope this helps.

Registering derived classes with reflection, good or evil?

As we all know, when we derive a class and use polymorphism, someone, somewhere needs to know what class to instanciate. We can use factories, a big switch statement, if-else-if, etc. I just learnt from Bill K this is called Dependency Injection.
My Question: Is it good practice to use reflection and attributes as the dependency injection mechanism? That way, the list gets populated dynamically as we add new types.
Here is an example. Please no comment about how loading images can be done other ways, we know.
Suppose we have the following IImageFileFormat interface:
public interface IImageFileFormat
{
string[] SupportedFormats { get; };
Image Load(string fileName);
void Save(Image image, string fileName);
}
Different classes will implement this interface:
[FileFormat]
public class BmpFileFormat : IImageFileFormat { ... }
[FileFormat]
public class JpegFileFormat : IImageFileFormat { ... }
When a file needs to be loaded or saved, a manager needs to iterate through all known loader and call the Load()/Save() from the appropriate instance depending on their SupportedExtensions.
class ImageLoader
{
public Image Load(string fileName)
{
return FindFormat(fileName).Load(fileName);
}
public void Save(Image image, string fileName)
{
FindFormat(fileName).Save(image, fileName);
}
IImageFileFormat FindFormat(string fileName)
{
string extension = Path.GetExtension(fileName);
return formats.First(f => f.SupportedExtensions.Contains(extension));
}
private List<IImageFileFormat> formats;
}
I guess the important point here is whether the list of available loader (formats) should be populated by hand or using reflection.
By hand:
public ImageLoader()
{
formats = new List<IImageFileFormat>();
formats.Add(new BmpFileFormat());
formats.Add(new JpegFileFormat());
}
By reflection:
public ImageLoader()
{
formats = new List<IImageFileFormat>();
foreach(Type type in Assembly.GetExecutingAssembly().GetTypes())
{
if(type.GetCustomAttributes(typeof(FileFormatAttribute), false).Length > 0)
{
formats.Add(Activator.CreateInstance(type))
}
}
}
I sometimes use the later and it never occured to me that it could be a very bad idea. Yes, adding new classes is easy, but the mechanic registering those same classes is harder to grasp and therefore maintain than a simple coded-by-hand list.
Please discuss.
My personal preference is neither - when there is a mapping of classes to some arbitrary string, a configuration file is the place to do it IMHO. This way, you never need to modify the code - especially if you use a dynamic loading mechanism to add new dynamic libraries.
In general, I always prefer some method that allows me to write code once as much as possible - both your methods require altering already-written/built/deployed code (since your reflection route makes no provision for adding file format loaders in new DLLs).
Edit by Coincoin:
Reflection approach could be effectively combined with configuration files to locate the implmentations to be injected.
The type could be declared explicitely in the config file using canonical names, similar to MSBuild <UsingTask>
The config could locate the assemblies, but then we have to inject all matching types, ala Microsoft Visual Studio Packages.
Any other mechanism to match a value or set of condition to the needed type.
My vote is that the reflection method is nicer. With that method, adding a new file format only modifies one part of the code - the place where you define the class to handle the file format. Without reflection, you'll have to remember to modify the other class, the ImageLoader, as well
Isn't this pretty much what the Dependency Injection pattern is all about?
If you can isolate the dependencies then the mechanics will almost certainly be reflection based, but it will be configuration file driven so the messiness of the reflection can be pretty well encapsulated and isolated.
I believe with DI you simply say I need an object of type <interface> with some other parameters, and the DI system returns an object to you that satisfies your conditions.
This goes together with IoC (Inversion of Control) where the object being supplied may need something else, so that other thing is automatically created and installed into your object (being created by DI) before it's returned to the user.
I know this borders on the "no comment about loading images other ways", but why not just flip your dependencies -- rather than have ImageLoader depend on ImageFileFormats, have each IImageFileFormat depend on an ImageLoader? You'll gain a few things out of this:
Each time you add a new IImageFileFormat, you won't need to make any changes anywhere else (and you won't have to use reflection, either)
If you take it one step further and abstract ImageLoader, you can mock it in Unit Tests, making testing the concrete implementations of each IImageFileFormat that much easier
In vb.net, if all the image loaders will be in the same assembly, one could use partial classes and events to achieve the desired effect (have a class whose purpose is to fire an event when the image loaders should register themselves; each file containing image loaders can have use a "partial class" to add another event handler to that class); C# doesn't have a direct equivalent to vb.net's WithEvents syntax, but I suspect partial classes are a limited mechanism for achieving the same thing.