How to get the time which is spend for loading the flash object? - actionscript-3

how to get the time which tooks the flash object to load inside the browser, from the creation of the object untill it's ready state ?

If you just want to measure the loading time of the Flash object, you can just use FireBug. But if you want to know when a Flex application is completely ready for usage (i.e. all RSL's loaded; all initial data loaded), I think there are two approaches. One within the app, using a custom preloader to start timing and stop timing when your conditions are met. The other through JavaScript and ExternalInterface. Of which I reckon the latter will give you the most accurate result, because there will probably already be a delay before the preloader is loaded.
JavaScript and ExternalInterface
I have never done this so I'm just going to explain my thoughts. In Javascript you create a 'date' object when the Flash object starts loading. You're probably using SWFObject to inject the Flash object into the page, so you can probably hook up somewhere in there. Then inside your Flex application, when the necessary conditions are met (you define what those are), you use the ExternalInterface.call() to tell JavaScript that the Flex app is ready. Make a new 'date' and subtract the first 'date', and you have your loading time.
More info on using ExternalInterface can be found in the docs: http://help.adobe.com/en_US/as3/dev/WS5b3ccc516d4fbf351e63e3d118a9b90204-7cb2.html
more detail
Create the JavaScript function that we'll call when the app is ready:
function onFlexAppReady() {
var end = new Date().getTime();
var loadTime = end - start; //in ms.
}
Now in the code that was generated by FlashBuilder, add the start time before the swf is injected:
var start = new Date().getTime();
swfobject.embedSWF(
"MyFlexApp.swf", "flashContent",
"100%", "100%",
swfVersionStr, xiSwfUrlStr,
flashvars, params, attributes);
Lastly, in your Flex app, when the right conditions are met, call the JavaScript function:
ExternalInterface.call("onFlexAppReady");
Again, this is all untested code, but it should get you started.

Related

Loader.as returning blank bitmap

I have an application which pulls in Bitmap resources from a server - currently I use the Loader class to do this, then, once they're loaded, generate a BitmapData based on the loader dimensions and draw the instance of Loader directly to it (the BitmapData is used for Away3D textures as well as Bitmap instances, so I have no need for the Loader once fetched).
This has always worked for me, but recently I started getting 0x0 Loaders, and invalid BitmapData as a result.
I stopped doing this:
this.imageBitmap = new BitmapData(this.imageLoader.width, this.imageLoader.height, true, 0);
..and started doing this:
this.imageBitmap = new BitmapData(event.target.content.width, event.target.content.height, true, 0);
Where event is the Event.COMPLETE event fired by the loader. This fixed the dimension problem, but the BitmapData is just a plain white bitmap (and it's set to transparent by default, so this is being drawn into it). Frustratingly, this doesn't happen every time, if I refresh the application it works as it should around 25% of the time, otherwise it plays up like this.
I've got a tight deadline and I'm really screwing about this, if anyone could help or suggest a better way of doing it you'd really be saving my neck!
Sounds like you need to adjust the image decoding policy for the loader - to ensure it decodes the image before COMPLETE fires - then the width and height etc should be reliable.
To do it, just add a suitable LoaderContext object to the Loader.load method:
var loaderContext:LoaderContext = new LoaderContext();
//set decode policy
loaderContext.imageDecodingPolicy = ImageDecodingPolicy.ON_LOAD;
//load image
loader.load(yourUrl, loaderContext);
The default decode policy is ImageDecodingPolicy.ON_DEMAND - which doesnt decode the image until it is actually required.
Lang docs: http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/system/ImageDecodingPolicy.html
Fixed it, stupid oversight and bit of an obscure situation but I'll leave an answer in case anyone runs into something similar.
My loader is contained in an Asset class - when another object requires the internal bitmap, it queries this class - if the bitmap's present, it returns it, if not it loads it with a loader and registers a callback for a COMPLETE event which is fired when the Loader has loaded and transferred its contents to a BitmapData instance.
The stupid mistake I'd made was that, if several objects were querying the same (as-yet-unloaded) asset, it would start reloading the asset each time, creating a new Loader as it did so...so when the first Loader was complete, it would fire an event but no reference to it would exist, not only creating a memory leak but causing the Asset class to extract the BitmapData from the most-recently-created Loader, which was not complete! The asynchronous nature of Loader is the reason it worked sometimes, as on occasion the final Loader would be ready in time for BitmapData extraction.
Simple solution was to create an internal boolean, _isLoading, which is set to true the first time load() is called - any subsequent calls are ignored if it's true, but callbacks still registered, works a treat!

Loading an XML in ActionScript 3 before an event listener happens

I'm trying to fill some data from an xml feed we made into my Flash movie. The main action of this is in the constructor for MediaElementJS's .as file.
Anyway, the main problem is that I keep reading there is no way to load a URL synchronously in AS3 (which i still find hard to believe). This constructor calls both parse('url') and a function addEventListener(EVENT.ADDED_TO_STAGE, initializeAds);
Now the ads need info from the XML but the XML aint ready yet. I tried to call the ads at the end of the XML parser when I knew it would be prepped but it messes them up and the ad values never change from their defaults..
Oh wherefor art thou actionscript locking mechanism..
So is there anyway to preload data from a URL?
CODE:
public function LoadXML(e:Event):void
{
removeEventListener(Event.COMPLETE, LoadXML);
var xmlData:XML = new XML(e.target.data);
episodeData.pre.type = xmlData.episode.pre.ad.#type;
episodeData.pre.url = xmlData.episode.pre.ad.text();
episodeData.video = Number(xmlData.episode.video.#id); /*************** I CAN'T REMEMBER ***********/
episodeData.pageTitle = xmlData.episode.video.#pagetitle;
episodeData.title = xmlData.episode.video.#title;
episodeData.source = xmlData.episode.video.source.text();
episodeData.post.type=xmlData.episode.post.ad.#type;
episodeData.post.url=xmlData.episode.post.ad.text();
episodeData.nextEpisode=xmlData.episode.post.nextepisode.text(); //if not empty redirect to this
xmlLoading = false;
//THIS IS WHERE I TRIED TO CALL THE FUNCTION I NEED TO LOAD LATER
}
public function parse()
{
var xmlLoader:URLLoader = new URLLoader();
//var xmlData:XML = new XML();
xmlLoader.load(new URLRequest(rootURL + '/episode.aspx?associd=' + _episode));
//xmlLoader.addEventListener(Event.COMPLETE, processXML);
xmlLoader.addEventListener(Event.COMPLETE, LoadXML);
}
I've tried it with a static URL address and whatnot of course but no dice.
The code in the constructor works if I dynamically assign a static value but if I try chaining to events together to get the dynamic value and dynamic assignment it crunches.
In the constructor, definitely runs both by themselves:
parse();
// Google IMA EventListener
addEventListener(Event.ADDED_TO_STAGE, initialize);
Loading URLs is always asynchronous, so add the event listener in the response function for the URL loader.
Now your question sounds like you tried that but had some problem, so post that code and let us take a look.
Edit START
When I have multiple asynchronous calls that happen and I need something to happen after both of them are done I usually use booleans to store if each one has happened yet, then in a third function they both call I check both the booleans.
Here's how I'd do that:
protected function viewnavigatorapplication1_preinitializeHandler(event:FlexEvent):void
{
var loader1:Loader = new Loader();
var loader2:Loader = new Loader();
loader1.addEventListener(Event.COMPLETE, loader1_completeHandler);
loader1.load(new URLRequest("http://www.whitehouse.gov"));
loader2.addEventListener(Event.COMPLETE, loader2_completeHandler);
loader2.load(new URLRequest("http://www.nasa.gov"));
}
private function loader1_completeHandler():void
{
loader1Done = true;
//Maybe do some stuff here
moveOn();
}
private function loader2_completeHandler():void
{
loader2Done=true;
//Maybe do some stuff here
moveOn();
}
private function moveOn():void
{
if(!loader1Done||!loader2Done)
return;
//Do whatever needs to be done once both asynchronous events have completed
}
If this isn't your problem I think you need to provide more of the code in place of the comments that indicate other things happen, because it is a bit unclear.
For example I'm not sure what you mean by "The code in the constructor works if I dynamically assign a static value but if I try chaining to events together to get the dynamic value and dynamic assignment it crunches." Also since there's no example of the data or what the rootURL is there's no way to debug from here to understand what's going wrong.
Since there's no error we would need to be able to re-compile some portion of your code locally to give any better feedback.
Edit END
Blocking or synchronous calls are a horrible idea with regard to network communications due to the lack of reliability of networks and/or servers. If a front end application locked up to wait for a response before doing any other processing it would result in a horrible user experience, this is why there is no synchronous remote calls.
What happens with a synchronous call when the server bombs out, the client remains locked even though no response will result, the user can't interact with anything else in the front-end because it's waiting for said response which will never come? It's much better that remote calls of any sort are done in an asynchronous fashion, the same is true with local disk access in Java (or otherwise) where using asynchronous non-blocking calls is generally a better way to go to allow the other processes within an application to continue regardless of the state or use on the disk.
What you're doing should work just fine, you make a call to a remote service, it responds with some result and hits your "listener" or "callback" function then you want to do something with the results you can call another function, and the data is there.
It sounds to me like the only thing that's not happening is updates after the fact aren't being reflected in the UI, this is probably due to a lack of Bindable metadata/event dispatching for the properties. Have you inspected the result in the event that returns, have you put breakpoints in the method that is meant to be called after the data has returned? What you're doing is completely possible and it even looks like you have most of it right, but there's definitely something your doing wrong that's resulting in you not being able to make this work. If you can explain the behavior a bit clearer that will help, also what do you do here:
//THIS IS WHERE I TRIED TO CALL THE FUNCTION I NEED TO LOAD LATER

Flash debugger behaving differently from the player with AS3 and Events

Why this works on flash professional's debugger, but brings null on the compiled SWF?
var firstParameter:SomeObject = new SomeObject();
someLoader = new Loader();
someLoader.contentLoaderInfo.addEventListener(
Event.COMPLETE
, function(evt) {
onLoaded(evt, firstParameter);
}
, false
);
function onLoaded (evt:Event, param:SomeObject):void {
mcOnSceneForTracing.text = param; // this is used for SWF debugging
}
For the record:
To make it work without any issues this can be "solved" by creating a separate scope. However, here I'm wondering why, then, this example even works on the debugger at least.
And, please, if you have a better way other than using two anonymous functions to pass parameters, variables, values, whatever through an Event, do tell! I'm not willing to extend the Event, tho. Too 2005.
mcOnSceneForTracing is what I'm using to "trace" outside the debugger. Suggestions are also accepted here for better (and simpler) ways to do it! I've heard Vizzy is good, but haven't tried it yet.
My guess would be: When loading your resource from the debugger player, the operation finishes instantly, and thus firstParameter is available when your anonymous listener function is called, but when running the swf elsewhere, the load operation takes longer, and then the reference to firstParameter is lost, since it is a local variable.

ActionScript-3 timing issue / unwanted background multi-threading

I created a new class with private vars and public get properties.
When I create a new instance of the class, it loads text files content to the private vars - it probably takes a bit of time to load it.
After the new instance created, I try to get the value of the private var with the get property:
var item1:MyItem = new MyItem("0001");
trace(item1.ItemName);
Well, The output is blank.
The string that ItemName points to is not undefined, it contains data.
So, it's like a timing issue, and ActionScript is probably running the code using background multi-threading, so it's calling the trace command before it finished to run all methods in the MyItem c'tor (methods that load the text file data into the String var that ItemName points to).
Is there any way to force ActionScript avoid using this unwanted "background multi-threading", and run the code normally (by the order of the commands)?
I mean like "Don't run the 2nd command until you finished running the 1st one".
Thanks for any help..
Freddy
It's not multi-threading, loading a text file externally is just a completely asynchronous operation. Within your MyItem class, you need to have an Event.COMPLETE handler for that Loader. From there, there here is what I'd do:
Option 1: In MyItem's COMPLETE handler for the file load, set a flag. The class that uses the getter must check the flag via another getter to see if the data is there, and either use it (if it's there) or set up a listener to wait for it (if it's not). Once the data is loaded, you have immediate synchronous access to it (it's cached).
Option 2: An alternative to keeping the "isLoaded" flag within MyItem would be to have MyItem's Loader COMPLETE handler dispatch it's own TEXT_LOADED event. Then, the instance responsible for creating the MyItem instance would listen for that, and know not to ask for the contents of that text file until it was there.
Either approach will work. It is up to you to figure out which one makes sense. My first option potentially avoids an unnecessary listener if you don't expect to access the loaded data right away (i.e. you're loading the text at startup for use sometime later). The second approach makes sense if you do expect to make use of the text file's data the instant it loads.
Ideally what you'd want to do is implement the Observer Pattern:
Add an event handler to your MyItem class for the Loaded event of whatever component/class you're using to load your XML.
Add an event to your MyItem class that will bubble the Loaded event from Step 1 so that clients of your MyItem class can attach a handler to it. Fire this event inside the Loaded handler you created in Step 1.
Attach an event handler to the event you created in Step 2 and place your trace code in that handler.
Your code is in fact running in a single thread, however the typical data loading classes in Actionscript are asynchronous. It is likely that the data has not loaded before you call trace. To be notified of when the data is loaded you should use an event listener on the loading object.
var loader:URLLoader = new URLLoader();
loader.addEventListener( Event.COMPLETE, onLoadComplete );
loader.load( new URLRequest( 'path_to_data.xml' ) );
function onLoadComplete( event:Event ):void
{
trace( loader.data );
}
The AS3 API docs have a more complete example.

Using AS3, should I declare variables globally or within a function only when they are needed?

I am working with URLLoader and URLRequest in this case.
I have two buttons. One listens for the mouse click event and then runs the following function (less code not applicable to this question):
function loadURL (e:MouseEvent):void {
....
var myRequest:URLRequest=new URLRequest("*URL*");
myRequest.method=URLRequestMethod.POST;
myRequest.data=postVars;
var myLoader:URLLoader = new URLLoader();
myLoader.load(myRequest);
....
}
The other button, when clicked, calls another function, say resetAll, that then resets the "session" by clearing out all the current variables and canceling anything currently in progress. Within that function I want to call myLoader.close(myRequest); but myLoader is not accessible from within resetAll.
In this case, should I declare var myRequest:URLRequest=new URLRequest("*URL*"); and var myLoader:URLLoader = new URLLoader(); outside of the function even if I do not need them yet?
I think I am missing some common sense knowledge of AS3 here, but not sure what it is. It would be appreciated if someone could fill me in on best practice in this case.
You can declare URLLoader variable globally and use local declaration or URLRequest variable.
URLRequest is anyway you have to recreate for every new requests, declaring them locally would be more safer for GC to collect it after its use.
URLLoader makes no sence re creating everytime, you can just pass new URLReqest object into Load method everytime you want to load something from server.
if this function is executed only once, you can use the variables from inside the function.
if this function is executed more then once in the life-time of the application you should declare the variables once and then only reconfigure or reinstantiate them.
Another thing, if you need to use those variables outside the function then you should of course declare them globally. (resetAll)
In some cases, closures are very useful. (Especially, for handling events or for controlling asynchronous codes.)
You can keep all the references of local variables at a time.
But when the source code of closures goes huge in the function, you should think about moving them into another class.
Here is an example
Closure Example - wonderfl build flash online
One thing you may think is the cost of the closures.
Executing closures costs much more than usual codes but it's negligible for ordinal cases.