In Starling projects, we need a startup class that extends flash.display.Sprite
or flash.display.MovieClip
. In this class, we create a starling.core.Starling
instance, and we set up behavior for things like resizing the view port and pausing our app or game when it goes into the background. For many projects, this class looks mostly the same. When I create a new project, I usually just copy the startup class from an existing project and modify it to pass in a different Starling root class. It would be ideal if I could simply abstract this bootstrap code away instead.
Flex applications require a significant amount of bootstrapping code too. We don’t deal with any of it, though, because the Flex SDK compiler abstracts much of it away. We can simply create a simple MXML file extending spark.components.Application
:
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark">
</s:Application>
However, behind the scenes, a Flex SWF starts up with an mx.managers.SystemManager
instance as the root display object. The spark.components.Application
instance isn’t the root. It’s a child. Once the SWF fully loads and the Flex framework is ready, the SystemManager
instantiates the Application
and adds it to the display list.
You don’t need to worry about this bootstrapping code in Flex because the spark.components.Application
class defines the following metadata:
[Frame(factoryClass="mx.managers.SystemManager")]
As long as you subclass Application
this metadata will tell the compiler that your class should be included on the second frame of the SWF, and the class defined in the factoryClass
should be the root display object instantiated when the SWF starts up. Once the first frame loads, the SystemManager
can display a preloader while the second frame is loading. When the second frame is ready, the SystemManager
instantiates the Application
and adds it to the display list.
[Frame]
metadata isn’t restricted to Flex applications. An ActionScript project built with the Flex SDK compiler may use [Frame]
metadata too. In fact, some developers may have already used this metadata with Starling projects to create a preloader for SWFs that run in a web browser.
While it isn’t a strict requirement for supporting MXML in Feathers, I want the new project experience to be as simple Flex’s. We shouldn’t need to manually instantiate Starling and set up code to resize the view port and things. It should be part of some hidden bootstrap code. A new Feathers MXML application should look something like this:
<?xml version="1.0" encoding="utf-8"?>
<feathers:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:feathers="library://ns.feathersui.com/mxml">
</feathers:Application>
The upcoming Feathers MXML SDK will include a feathers.core.Application
class that takes advantage of [Frame]
metadata.
package feathers.core
{
import feathers.controls.LayoutGroup;
[Frame(factoryClass="feathers.core.StarlingBootstrap")]
public class Application extends LayoutGroup
{
public function Application()
{
super();
this.autoSizeMode = LayoutGroup.AUTO_SIZE_MODE_STAGE;
}
}
}
All the bootstrapping happens behind the scenes in this feathers.core.StarlingBootstrap
class, which serves a similar purpose as the Flex SystemManager
. However, instead of initializing the Flex framework, it sets up Starling instead. It passes our subclass of feathers.core.Application
to Starling to use as the root class. It listens for the native stage Event.RESIZE
to resize the Starling view port and stage. It looks just like any normal startup class for a Starling project. Not much different than Starling’s Scaffold_Mobile
sample or the Feathers ComponentsExplorer
example.
The main difference between StarlingBootstrap
and other startup classes is that StarlingBootstrap
must have a method named info()
. The compiler generates a subclass of StarlingBootstrap
and overrides info()
to make it return an object with a number of properties. This object stores things like the name of the Starling root class and, optionally, a Feathers theme. You can see a slightly simplified example of this generated subclass below:
public class _MyFeathersApp_feathers_core_StarlingBootstrap
extends feathers.core.StarlingBootstrap
{
public function _MyFeathersApp_feathers_core_StarlingBootstrap()
{
super();
}
private var _info:Object;
override public function info():Object
{
if (!_info)
{
_info = {
rootClassName: "MyFeathersApp",
themeClassName: "feathers.themes.MetalWorksDesktopTheme"
};
}
return _info;
}
}
You can see that our main class was named MyFeathersApp
. A string representation is stored in the rootClassName
property returned by the info()
function. StarlingBootstrap
uses getDefinitionByName()
to access the Class
:
var rootClassName:String = info()["rootClassName"];
var rootClass:Class = Class(getDefinitionByName(rootClassName));
Once it has the Class
reference, StarlingBootstrap
can pass it to Starling to instantiate when Stage 3D is ready. The compiler will automatically ensure that MyFeathersApp
is compiled into the SWF, even though it is not strictly imported here.
Anyone will be able to read the ActionScript code that gets generated by the Feathers MXML SDK compiler. Similar to the Flex SDK, we will be able to add the -keep
compiler argument to include a folder of generated ActionScript files in the same place as the compiled SWF.
Additionally, using the StarlingBootstrap
class to bootstrap a Feathers MXML application won’t be strictly required. Custom [Frame]
metadata may be added to any subclass of feathers.core.Application
that will override its default metadata. This will let us provide a different startup experience, if needed. We might want to customize the stage size to support contentScaleFactor, for instance. Ideally, the bootstrapping mechanism should provide acceptable defaults for most projects, while keeping things as flexible as possible for more advanced requirements.
Thanks for the great job Josh.
Keep going.
Hey Josh,
Great start on abstracting to MXML … Feathers MXML would be a brilliant add-on and frankly I do think that you should go with crowd funding on this – within the RIA developers community, a GPU accelerated UI to replace the old buggy flex components (or amend them) would be a big deal and will help us all a lot when building business oriented apps. Please, go with kickstarter or similar – put down a 100k+ goal and add $20 to $1k options for funding – I am 100% sure that those of us serious about AIR development for mobile will get on board in a heartbeat – I myself am ready to pledge a $100 right away for this sort of project and would contribute with whatever I can to speed up the development process. So, single sponsor funding sounds ok, but it comes with string attached (I’m sure) which perhaps is more focused on the sponsor’s own agenda.
Keep up the great work!
Cheers:
-Nick