how to call an external function from inside a class? - apache-flex

i want to call an external function inside a class. thats the code;
in checkConnectionStatus function,
this[_funcNameForSucceededCon].apply(); doesnt work because "this" is the class, not the Application. How can i reach Application at this time or what can i do?
any help will be greatly appreciated.
best regards,
mira.
package myLibrary
{
import air.net.URLMonitor;
import flash.events.Event;
import flash.events.StatusEvent;
import flash.net.URLRequest;
public class connectionControl
{
private var _urlReq:URLRequest;
private var _urlMonitor:URLMonitor;
private var _funcNameForSucceededCon:String;
private var _funcNameForFailedCon:String;
public function connectionControl(targetURL:String, funcNameForSucceededCon:String, funcNameForFailedCon:String)
{
_urlReq = new URLRequest(targetURL);
_urlMonitor = new URLMoniotor(_urlReq);
_urlMonitor.addEventListener(StatusEvent.STATUS, checkConnectionStatus);
_funcNameForSucceededCon = funcNameForSucceededCon;
_funcNameForFailedCon = funcNameForFailedCon;
if(_urlMonitor.running == false)
{
_urlMonitor.start();
}
else
{
_urlMonitor.stop();
_urlMonitor.start();
}
}
private function checkConnectionStatus(e:Event):void
{
_urlMonitor.removeEventListener(StatusEvent.STATUS, checkConnectionStatus);
if(_urlMonitor.available)
{
this[_funcNameForSucceededCon].apply();
}
else
{
this[_funcNameForFailedCon].apply();
}
}
}
}

You have passed the name of the function to be serving as a callback. Use instead the function itself and pass it to connectionControl.
public class connectionControl
{
private var _funcSucceededCon:Function;
private var _funcFailedCon:Function;
public function connectionControl(targetURL:String, funcSucceededCon:Function, funcFailedCon:Function)
{
_urlReq = new URLRequest(targetURL);
_urlMonitor = new URLMoniotor(_urlReq);
_urlMonitor.addEventListener(StatusEvent.STATUS, checkConnectionStatus);
_funcSucceededCon= funcSucceededCon;
_funcFailedCon= funcFailedCon;
...
And:
if(_urlMonitor.available)
{
_funcSucceededCon();
}

Related

AS3 / Flex 3 Staggered Remoting + Queue

I am trying to make a class that staggers the net connections calls by a certain amount to not put too much pressure on my server, and so I don't have a dozen net connectors running around in my code.
I want a class that I can send a call command to, the class adds the call to the queue, and then about every one second it see if anything is in the queue, and if so calls it. This is what I have so far.
package net
{
import flash.events.TimerEvent;
import flash.net.NetConnection;
import flash.net.Responder;
import flash.utils.Timer;
public class Server
{
private static var gateway:String = "http://localhost/gateway.php";
private static var queue:Vector.<ServerNode>
private static var nc:NetConnection;
private static var instance:Server = null;
private static var res:Responder;
private var timer:Timer;
public function Server(e:ServerEnforcer) {
nc = new NetConnection();
queue = new Vector.<ServerNode>();
timer = new Timer(1000);
timer.addEventListener(TimerEvent.TIMER, execCall);
timer.start();
}
public static function getInstance():Server {
if (instance == null) {
instance = new Server(new ServerEnforcer);
}
return instance;
}
private function execCall(e:Event):void {
if (queue.length > 0) {
var node:ServerNode = queue.pop();
nc.call(node.method, node.res, node.args);
}
}
public function call(method:String, success:Function, failure:Function, ...args):void {
queue.unshift(new ServerNode(method, success, failure, args));
}
private function serverFailure(event:Object):void {
trace("Server Failure : " + event.description);
}
}
}
import flash.net.Responder;
class ServerEnforcer { }
class ServerNode {
public var method:String;
public var success:Function;
public var failure:Function;
public var args:Array;
public var res:Responder
public function ServerNode(_method:String, _success:Function, _failure:Function, _args:Array) {
method = _method;
success = _success;
failure = _failure;
res = new Responder(success, failure);
args = _args;
}
}
Now when I call
Server.getInstance().call("Fetch.getData", parseAllData, onError)
public function parseAllData(event:Object):void {
trace("Victory!");
}
public function onError(event:Object):void {
trace("Error :" + event);
}
absolutely nothing happens. Any idea why or a point in the right direction why this isn't working?
You created an instance of the NetConnection, but haven't actually initiated a connection with the server.
In other words,
nc.connect(gateway);
is missing.
See NetConnection documentation for more information on that class.

implementing singleton class for Actionscript

I know actionscript does not allowed private contstructor at any time and But if i want to write a sinlgleton class in action script So how to implement it in actionscript.
Can anyone provide an sample example of a singleton pattern in actionscript?
I use something like this:
package singletons
{
[Bindable]
public class MySingleton
{
private static var _instance:MySingleton;
public function MySingleton(e:Enforcer) {
if(e == null) {
throw new Error("Hey! You can't do that! Call getInstance() instead!");
}
}
public static function getInstance():MySingleton {
if(_instance == null) {
_instance = new MySingleton (new Enforcer);
}
return _instance;
}
}
}
// an empty, private class, used to prevent outside sources from instantiating this locator
// directly, without using the getInstance() function....
class Enforcer{}
You need to alter Alxx's answer slightly as it doesn't stop new Singleton() from working...
public class Singleton {
private static var _instance : Singleton;
public function Singleton( newBlocker : ClassLock ) {
}
public static function getInstance() : Singleton {
if ( _instance == null ) {
_instance = new Singleton( new ClassLock() );
}
return _instance;
}
}
class ClassLock{}
The private class is used by the Singleton to stop other classes simply doing new Singleton() initially and then getting a second instance by doing getInstance().
Note that this still isn't watertight... If someone is determined to break it, they can get access to the private class, but this is about the best option for Singletons.
basically, all answers are right, those of reid and gregor provide more compile time safety. I suppose, the best thing is however, to declare an interface for the singleton and a private implementor exposed through a static class:
package {
interface IFoo {
function foo():void;
}
}
and then:
package Foo {
private static var _instance:IFoo;
public static function getInstance():IFoo {
if (_instance == null) _instance = new Impl();
return _instance;
}
}
class Impl implements IFoo {
public function foo():void {
trace("fooooooooooooooooooo");
}
}
this doesn't rely on runtime errors for safety. Also, it lowers coupling.
greetz
back2dos
public class Singleton {
private static var _instance:Singleton;
public **static** function get instance():Singleton
{
if (_instance == null)
{
_instance = new Singleton();
}
return _instance;
}
public function Singleton()
{
if (_instance != null) throw new Error("You can't create Singleton twice!");
}
}
Runtime check in lack of private constructor.
I use this approach ...
package
{
public class Main
{
private static var _instance:Main;
private static var _singletonLock:Boolean = false;
/**
* Creates a new instance of the class.
*/
public function Main()
{
if (!_singletonLock) throw new SingletonException(this);
}
/**
* Returns the singleton instance of the class.
*/
public static function get instance():Main
{
if (_instance == null)
{
_singletonLock = true;
_instance = new Main();
_singletonLock = false;
}
return _instance;
}
}
}
... not as terse as some other methods but it's absolutely safe and there's no need for an empty package-level class. Also note the shortcut with SingletonException which is a class that extends the AS3 Error class and saves typing some code when using more than one Singleton ...
package
{
public class SingletonException extends Error
{
public function SingletonException(object:Object)
{
super("Tried to instantiate the singleton " + object + " through it's constructor."
+ " Use the 'instance' property to get an instance of this singleton.");
}
}
}

Simplify AS3 binding/event-dispatching code

There are 3 properties (example 1):
[Bindable] public var name:String;
[Bindable] public var email:Number;
[Bindable] public var address:Boolean;
I needed to have 3 helper methods that will be bindable too (example 2):
[Bindable] public var name:String;
[Bindable] public var email:Number;
[Bindable] public var address:Boolean;
public function get nameIsOk():Boolean { return !Strings.isEmpty(name) }
public function get emailIsOk():Boolean { return email == 3 }
public function get addressIsOk():Boolean { return address }
Sure, the code above doesn't work. I made it work by doing this (example 3):
private var _name:String
[Bindable("nameChanged")]
public function get name():String { return _name }
public function set name(v:String):void { _name = v; dispatchEvent(new Event("nameChanged")) }
[Bindable("nameChanged")]
public function get nameIsOk():Boolean { return !Strings.isEmpty(name) }
private var _email:Number
[Bindable("emailChanged")]
public function get email():Number { return _email }
public function set email(v:Number):void { _email = v; dispatchEvent(new Event("emailChanged")) }
[Bindable("emailChanged")]
public function get emailIsOk():Boolean { return email == 3 }
private var _address:Boolean
[Bindable("addressChanged")]
public function get address():Boolean { return _address }
public function set address(v:Boolean):void { _address = v; dispatchEvent(new Event("addressChanged")) }
[Bindable("addressChanged")]
public function get addressIsOk():Boolean { return address }
It does work, but now it is bloated.
Is there a way to reduce this code (example 3) to something smaller (like example 2)?
UPDATE:
Kudos to just_a_dude for nice answer. Here is the final version:
[Bindable] public var name:String;
[Bindable] public var email:Number;
[Bindable] public var address:Boolean;
public function Remixer() {
for each (var f:String in Strings.split("name email address")) {
ChangeWatcher.watch(this, f, onChange)
}
}
private function onChange(e:PropertyChangeEvent):void {
dispatchEvent(new Event(e.property + "Changed"))
}
[Bindable("nameChanged")]
public function get nameIsOk():Boolean { return !Strings.isEmpty(name) }
[Bindable("emailChanged")]
public function get emailIsOk():Boolean { return email == 3 }
[Bindable("addressChanged")]
public function get addressIsOk():Boolean { return address }
Not sure if this is what you're looking for but you can use mx.binding.utils.ChangeWatcher to "watch" for property changes
<?xml version="1.0" encoding="utf-8"?>
<mx:Script>
<![CDATA[
import mx.events.PropertyChangeEvent;
import mx.binding.utils.ChangeWatcher;
[Bindable] public var firstName:String;
[Bindable] public var email:Number;
[Bindable] public var address:Boolean;
private var _watcher:ChangeWatcher;
private function init():void {
ChangeWatcher.watch(this, "firstName", propertyChangeHandler);
ChangeWatcher.watch(this, "email", propertyChangeHandler);
ChangeWatcher.watch(this, "address", propertyChangeHandler);
firstName = "foo";
email = 0;
address = true;
firstName = "bar";
email = 1;
address = false;
}
protected function propertyChangeHandler(event:PropertyChangeEvent):void {
var prop:Object = event.property;
var name:String = prop.toString() + "Changed";
// trace(name); // displays firstNameChanged or emailChanged or addressChanged
dispatchEvent(new Event(name));
}
]]>
</mx:Script>
Let me know if this helps
Cheers
I'm not sure if you need getters, but if not, a nice way to do it, is to just use a single function, and put your bindable strings as arguments.
if you put this in your object:
public function isOk(s:String):Boolean
{
return !Strings.isEmpty(s)
}
You would use it like this:
<mx:CheckBox selected="{yourObject.isOk(yourObject.name)}" />
Generally, if you put a function inside the "{}" with parameters which are bindable, it will be called each time that parameter changes.
I would encapsulate your functionality in a class. Do not repeat yourself :)

can not access MovieClip properties in flashDevelop

I know there is something I am doing wrong. In my controls I have keydown events that control my hero. As of right now, I am trying to rotate my hero but he refuses to turn . Below is my Hero Class, my control class, and gameobject class. pretty much all the classes associate with the controls class.
package com.Objects
{
import com.Objects.GameObject;
/**
* ...
* #author Anthony Gordon
*/
[Embed(source='../../../bin/Assets.swf', symbol='OuterRim')]
public class Hero extends GameObject
{
public function Hero()
{
}
}
}
Here is my Controls class. This is the class where I am trying to rotate my hero but he doesnt. The keydown event does work cause I trace it.
package com.Objects
{
import com.Objects.Hero;
import flash.events.*;
import flash.display.MovieClip;
/**
* ...
* #author Anthony Gordon
*/
public class Controls extends GameObject
{
private var aKeyPress:Array;
public var ship:Hero;
public function Controls(ship:Hero)
{
this.ship = ship;
IsDisplay = false;
aKeyPress = new Array();
engine.sr.addEventListener(KeyboardEvent.KEY_DOWN, keyDownListener);
engine.sr.addEventListener(KeyboardEvent.KEY_UP,keyUpListener);
}
private function keyDownListener(e:KeyboardEvent):void {
//trace("down e.keyCode=" + e.keyCode);
aKeyPress[e.keyCode] = true;
trace(e.keyCode);
}
private function keyUpListener(e:KeyboardEvent):void {
//trace("up e.keyCode=" + e.keyCode);
aKeyPress[e.keyCode]=false;
}
override public function UpdateObject():void
{
Update();
}
private function Update():void
{
if (aKeyPress[37])//Key press left
ship.rotation += 3,trace(ship.rotation ); ///DOESNT ROtate
}//End Controls
}
}
Here is GameObject Class
package com.Objects
{
import com.Objects.Engine;
import com.Objects.IGameObject;
import flash.display.MovieClip;
/**
* ...
* #author Anthony Gordon
*/
public class GameObject extends MovieClip implements IGameObject
{
private var isdisplay:Boolean = true;
private var garbage:Boolean;
public static var engine:Engine;
public var layer:Number = 0;
public function GameObject()
{
}
public function UpdateObject():void
{
}
public function GarbageCollection():void
{
}
public function set Garbage(garb:Boolean):void
{
garbage = garb;
}
public function get Garbage():Boolean
{
return garbage
}
public function get IsDisplay():Boolean
{
return isdisplay;
}
public function set IsDisplay(display:Boolean):void
{
isdisplay = display;
}
public function set Layer(l:Number):void
{
layer = l;
}
public function get Layer():Number
{
return layer
}
}
}
Looks like your keyUpListener and keyDownListener methods aren't calling the UpdateObject function.
Try listening for your KeyboardEvent on stage instead of engine.sr (not sure what that is)
If you put them on anything other than the stage you will need to click that specific thing first to give it focus for the events to work.
Also, the line:
ship.rotation += 3,trace(ship.rotation );
in your Control class looks a bit broken.

Arraycollection not capturing the thrown event?

I have a collection of objects and each object throws an event every time its value gets updated. Im trying to capture that event by adding a listener to the arraycollection that holds it (see main class) but its not working. Honestly I'm not sure this is the correct approach.
I'm avoiding using Collection.CHANGE because it fells into an infinite recursion ultimately ends in a stack overflow. Any ideas?
[Bindable]
public class NamesVO {
public var steveList:ArrayCollection; // array of SteveVO objects
public function NamesVO() {
steveList = new ArrayCollection();
}
public function rename():void {
for each(var steve:SteveVO in steveList) {
steve.rename();
}
}
}
[Bindable]
public class SteveVO extends EventDispatcher {
public static const VALUE_CHANGED:String = "VALUE_CHANGED";
public var code:String;
public var name:String;
public var _quantity:Number;
public function SteveVO() {
this.code = "";
this.name = "";
_quantity = 0;
}
public function get quantity():Number {
return _quantity;
}
public function set quantity(quantity:Number):void {
_quantity = quantity;
dispatchEvent(new Event(VALUE_CHANGED));
}
public function rename():void {
name = code + " - " + _quantity;
}
}
Main class:
names = new NamesVO();
names.steveList.addEventListener(SteveVO.VALUE_CHANGED, function():void {
names.rename(); // this anon function is not being executed!!
});
var steve:SteveVO = new SteveVO();
names.steveList.addItem(steve);
// names is bound on a datagrid and uses itemeditor for each SteveVO object
The VALUE_CHANGED event is not dispatched by the steveList array Collection so won't be detected by your listener. You could encapsulate the functionality you want inside the NamesVO class by detecting when an item is added to the array collection and adding a listener to the new steveVO object that dispatches the same event from NamesVO. Then just listen for that event in your main class.
Is there a reason to change all the names when one quantity is changed. Would it be better simply to call rename inside the set function of the steveVO class?
To implement the change:
import flash.events.Event;
import mx.collections.ArrayCollection;
import mx.events.CollectionEvent;
import mx.events.CollectionEventKind;
[Bindable]
public class namesVO
{
public var steveList:ArrayCollection; // array of SteveVO objects
public function namesVO()
{
steveList = new ArrayCollection();
steveList.addEventListener(CollectionEvent.COLLECTION_CHANGE,collChanged);
}
private function collChanged(e:CollectionEvent):void
{
if (e.kind == CollectionEventKind.ADD)
e.items[0].addEventListener(steveVO.VALUE_CHANGED,valueChanged);
}
private function valueChanged(e:Event):void
{
dispatchEvent(new Event(steveVO.VALUE_CHANGED));
}
public function rename():void
{
for each(var steve:steveVO in steveList)
{
steve.rename();
}
}
}
In the main class use:
names = new namesVO();
names.addEventListener(steveVO.VALUE_CHANGED, function():void
{
names.rename();
});
steve = new steveVO();
names.steveList.addItem(steve);
steve.quantity = 12;
Of course this is only an example and only includes the case where one item is added at a time.

Resources