According to the answers to this question here, the reason why I'm not seeing errors as I work in Flash Builder is that FB is "optimizing" them out because they aren't referenced at any point in the code execution. Is there an option to force Flash Builder to compile all files regardless of whether they're used in the software? This would make my development process a lot more intuitive.
The only way to do this is to actually reference the class somewhere in code that you know actually is being compiled, such as the Document Class in a .fla, or your Main.as file in a pure AS3 project. It can be as simple as declaring a variable of the given type, even if no value is ever assigned to it.
private var complieMe:OtherwiseUnreferencedClass;
// ^ This will cause your class to be compiled.
You need to reference each class somewhere in your project. The easiest/shortest way I've found to do this is to add an import followed by the class name in some common place, such as a script block in Main.mxml, although it really doesn't matter where:
import some.package.MyClass; MyClass;
Hope that helps.
Related
Suppose I have a non-qt object. For example, the QT static-only log handler. How does one cause this file handler to know where to go to look for the current configuration file without, say, hard-coding the application name, organization etc. into the static log-handler function?
I have tried defining a global pointer to the configuration that gets initialized during a startup phase, but this turns out to be a hairy problem to solve during the linking phase. Is there some particular "only-way-is-the-best-way" solution?
(New to QT; if there is an "accepted" or "intended" approach, I would like to take that)
May be create global singleton class?
Or set QSettings::setDefaultFormat() to ini near your binary?
Flash builder lets me insert metadata for events fired by a class, example:
[Event("myEvent", "flash.events.Event")]
public class MyClass() {
}
Is there any way to do the same for Exceptions?
Currently I have checked here, and can't see it documented. Perhaps it's not even worthwhile, what are your thoughts.
There are ways to create your own metadata; and add that into your app at compile time. Use the keep-as3-metadata compiler argument.
It will be up to you to write code to do something with it at runtime; or to build IDE extensions to make use of the code while writing the code.
To access such metadata at runtime, you'll need to perform some type of introspection. Here are some docs and another StackOverflow Question about this.
Many Flex Frameworks make use of custom metadata.
I'm working on an Flex application which uses many objects, e.g. LEDs, bulbs, gauges created in Flash. The objects internally consist of several small MovieClips and have their own logic inside. One of the initial requirements was that the objects have to be loaded at runtime, thus they were exported as SWF, not SWC. However, we ran into problem when we tried to duplicate loaded SWF. It turned out that MovieClip class doesn't have neither copying constructor nor method that would allow us to clone existing MovieClip. This way we'd end up loading an object every time from hdd, which involves a lot of overhead. Is it possible that language like ActionScript 3 doesn't have such a mechanism? Have we missed something out? If not, am I correct that the only solution is to use Flash Component Kit, make some custom components and include them as SWC at compile time?
After you load the MovieClip is it possible to use getDefinitionByName() as shown here?
http://livedocs.adobe.com/flex/3/langref/flash/utils/package.html#getDefinitionByName()
You are correct in that there is no built in way to duplicate a movieclip.
There are however work arounds. The esiest way as I see it is to give the movieclips classes.
You don't have to make the actual classes. Just write any name in the class field when setting up linkage on the top most movieclip that needs to be copied.
So a name for you LED movieclip, another name for the bulb etc.
The benifit is that now you have a class that you can initiate objects from.
No when you grap one of the movieclips you can duplicate it with the following method:
public function DuplicateDisplayObject(dO:DisplayObject):DisplayObject
{
if(dO == null)
return null;
var dOClass:Class = Object(dO).contructor;
return DisplayObject(new dOClass());
}
This assumes of cause that you can actually get a hold of one of the movieclips first. And mind you that it doesn't copy the state of the movieclip.
Another more importent note is that this only works if the you link the movieclips to classes. The classes doesn't have to exist (flash will create empty classes for you).
Other solutions could be:
Compiling against the classes without
including them (see the
"external-library-path" tag for the
flex compiler), and load the them at
runtime (from swf).
Compiling against the classes as a
RSL (Runtime Share Library) the swc
will be loaded at runtime.
Adobe has more info on how to do that, should be easy to find on their website.
A more exotic solution would be copy the bytecode of an object. Not sure if that would work with something on the displaylist, properly not.
About the solution using getDefinitionByName():
If I remember correctly you still need to give the movieclips fake classes, since getQualifiedClassName only returns MovieClip class. But I could be wrong.
Another solution:
private function duplicateImg(sourceLoaderInfo:LoaderInfo, target:Image):void
{
var ba:ByteArray = sourceLoaderInfo.bytes;
var dupCliploader:Loader = new Loader();
dupCliploader.contentLoaderInfo.addEventListener(
Event.COMPLETE, bytesLoaded);
dupCliploader.loadBytes(ba);
}
private function bytesLoaded(event:Event):void
{
var mc:MovieClip = event.currentTarget.content as MovieClip;
_img.source = mc;
_img.width = mc.width;
_img.height = mc.height+5;
}
I am developing a dynamic mocking framework for Flex/AS3 and am having trouble with private/support types (ie. those declared outside the package {} in a class file).
In my ABC "file", I am declaring the instance with the PROTECTED_NAMESPACE class flag and with a PRIVATE_NS multiname. I have also experimented with giving it the same namespace as the class it is subclassing (eg. PRIVATE_NS("ContainerClass.as$123")).
No matter what I do, I always get the following error after loadBytes:
VerifyError: Error #1014: Class ContainerClass.as$123::PrivateClass could not be found.
I have experimented with loading the generated bytecode into the same ApplicationDomain as the private class (I use a child domain by default). I even tried registering a class alias before the load (though that was a bit of a stretch).
Am I forgetting anything or is it simply a restriction of the AVM?
Please note that I am fully aware that this is illegal in ActionScript 3.0, I am looking for whether this is actually possible in the AVM.
Edit: For those interested in the work so far, the project is asmock and is on sourceforge.
I'm no expert with ABC files but I just don't think this is possible in the AVM2. I did several tests a while ago with the AS3 Eval lib and they all failed.
Related to dynamic mocking, I have filed an issue in Adobe bugbase, asking for a dynamic proxy mechanism: http://bugs.adobe.com/jira/browse/ASC-3136
I'm not sure what you mean by PRIVATE_NS("ContainerClass.as$123"), My reading of avm2overview.pdf 4.4.1 is that private namespaces are not permitted to have a name, hence that the "<class name>$<number>" namespace in debug output is generated for your convenience. I would assume that would mean you would have to hack your abc into the same abc tag in the source swf to access the namespace constant index (and that sounds too much like hard work to me!)
I haven't actually managed to generate a loading swf, though, so take this with a grain of salt.
Having gone back to look at this problem in ernest, I can definitively answer this question: private classes can only be referenced from the LoaderContext that loaded them
I have been able to add support for private interfaces by reproducing the interface in the loaded ABC 'file', but it cannot be coerced/cast back to the original private interface.
This is still useful for my requirements, as a private interface can be used to combine multiple interfaces.
I have a Flex application where load time is extremely important (consumer site). i want to be able to get something up on screen and then allow additional modules to be loaded as necessary.
The issue I'm facing is that the sum total of all the modules is much larger than if i were to include all the components in a single .swf file.
Its pretty obvious why. For instance the classes needed for web service access seem to take about 100kb. If I dont use those classes in my main.swf then they'll be included in EVERY module that uses them. So if I have 5 modules thats an extra 500kB wasted.
In theory I want 3 levels
main.swf - minimum possible layout / style / font / framework type stuff
common.swf - additional classes needed by module 1 + module 2 (such as web services)
module1.swf - module 1 in site
module2.swf - module 2 in site
I dont know if this is even possible.
I'm wondering if I can load swz/swf files for portions of the framework instead of the entire framework.
I really need to get my main app size down to 200Kb. It grows to 450kb when I add web services and basic datagrid functionality.
Any lessons learned would be appreciated.
I know this was awhile ago, but I figured I'd post another response in case anyone is still looking for an answer on this.
I've been looking into optimizing Flex apps and, after some checking into it, have decided to use Modules. Primarily 'cause they have such good options for optimization.
The two mxmlc commands you need are:
mxmlc -link-report=MyAppReport.xml MyApp.mxml
and
mxmlc -load-externs=MyAppReport.xml MyModule.mxml
My external swf (using the Flex Framework) is now only 21k. It's doing much (yet), but even as it does more and more, it will continue to use resources from the main app code.
Here's the batch file I created to speed up the process (you have to have put mxmlc in your Environment Path variable for it to work like this. Control Panel -> System -> Advanced -> Environment Variables, Edit the Path System Variable, adding the path to your mxmlc (requires a reboot)):
cd C:\Projects\MyProject\Develop\Modules
mxmlc -link-report=MyAppReport.xml C:\Projects\MyProject\Develop\Source\Main.mxml
mxmlc -load-externs=MyAppReport.xml MyModule.mxml
move /Y MyModule.swf ..\Runtime\Modules
More info here:
http://livedocs.adobe.com/flex/3/html/help.html?content=modular_4.html
Hope that helps!
Flex is a bit of a pig when it comes to file size. There really is only one way to get your app sizes down and that is to use an external swz for the framework. There is an Adobe Devnet article on Improving Flex application performance using the Flash Player cache which I recommend you read.
On a project I worked on we had problems with our preloading module sucking in classes that we didn't want. What we had to do was create interfaces to the classes that resided in the other modules and reference them that way. When the module is loaded we simply assigned a reference to the IApplicationModule in order to call our initialization code.
Also look into putting your classes into a seperate SWF file and then use ApplicationDomain to get access to the classes
(this code taken from this forum post which explains how to access classes loaded from modules in Flex)
private function loadContent(path:String):void
{
var contentLoader:Loader = new Loader();
contentLoader.contentLoaderInfo.addEventListener(
Event.COMPLETE,
loadContent_onComplete);
contentLoader.load(new URLRequest(path));
}
private function loadContent_onComplete (event:Event):void
{
var content:DisplayObject = event.target.content;
if(content is IFlexModuleFactory)
{
var content_onReady:Function = function (event:Event):void
{
var factory:IFlexModuleFactory = content as IFlexModuleFactory;
var info:Object = factory.info();
var instanceClass:Class = info.currentDomain.getDefinition(
info.mainClassName) as Class;
addChild (new instanceClass ());
}
content.addEventListener ("ready", content_onReady);
}
else
{
addChild (content);
}
}
There is an option on the command-line compiler to exclude class definitions that are already compiled into another swf. It works like this:
Compile the Main Application (which contains a loader) and opt to generate a report.
Compile the Module and opt to exclude classes in the above report.
You could look into the ModuleLoader class, maybe you can load up your core stuff in the first 200kbs then load the rest when and if it's needed.
Also it's worth bearing in mind that any SWC's you use are embedded at compile time whereas any SWF's are loaded at runtime.