Loading Random SWFs in a Strongly Typed Way

In a hurry? Skip to the code.

ActionScript 3 has given us true strong-typing; both compile time and runtime. This has many benefits from helping ensure code works once you actually compile as well as helping you debug runtime errors. The problem with perfect systems however is when you put in some chaos. The old adage, “garbage in, garbage out” holds true here. There are basically 2 ways to get weird stuff in Flash Player. You either load in external data and parse it, or you load in an external SWF.

The former is a little easier to deal with. Using E4X, if some XML node doesn’t exist, your code doesn’t throw exceptions. You can test against undefined, and set default values that match your ValueObjects (strongly typed classes that represent your data). In short, you can correctly write an XML parser that shields your app from bad data. Granted, his job is the most important as he’s the guardian against all loose wrenches in the gears. I’d say the majority of the bugs in the software I write in AS3 comes from a Factory letting bad or missing data through without either compensating with default values, or dispatching an appropriate error. In the end, though, if you do it right, you’re good.

External SWF’s, on the other hand aren’t really parsed. There are some bad asses doing some weird things with SWF’s, like loading them in for asset use only (since even Images are classes now that can be ripped out of externally loaded SWF’s, aka WinAMP skinning) or just Flash native data transfer objects like Aral does with SWX. For the most part, most use cases that call for loading in an external SWF are NOT positive beyond the 2 above. Some common use cases not including the above are:

  • loading in Flash Player 8, or below content
  • loading in Flash content created in the Flash IDE as opposed to Flex
  • loading in assets too big to compile into main SWF and un-linkable to Flex’ RSL work flow (audio, video)
  • 3rd party PRE-generated created SWF’s (even if AS3, still could use different component set)

This entry will target #2 and #3. For #1, here’s some morphine. For #4, good luck in the politic-infused blame game meetings.

Flash is damn good at creating creative content. Whether this is created in-house or outsourced to a 3rd party design firm, you can have this content be in Flash Player 9, AS3. While this sounds positive, it just sucks you cannot easily make this a part of your work flow. There are a few ways I’ve talked about in the past using the Flex Component Kit for Flash, which is now part of Flex 3, or simply writing wrapper classes. The Flex Component Kit is really great if you know ahead of time the scope of what the Flash will be, or it won’t be in flux. The same goes for the wrapper classes with those who are in more formalized programming environments.

However, sometimes you just get this problem that just defies all conventional ways of solving it. For example, a not-too-small widget was created in Flash CS3 using the new components. It may not easily portable to the Flex components in a reasonable time frame. What do you do? Attempt to get the Flash components to compile, with assets in Flex? I’ve tried this myself and wasted a bunch of time on it. I’m sure it’s possible, but I’m past trying, instead getting work done.

Real world scenario; DoubleClick’s In-Stream for AS3. Apparently you can get the SWC to work in Flex… we couldn’t. Even if we could, you can can’t test the S.O.B. locally, needs a webserver… So, you have no choice but to use Flash in this scenario.

In those situations, all you can do is load it in at runtime. The silver lining? Both are AS3. AS3 SWF’s can talk to each other. Your Flex SWF can call methods on the loaded Flash SWF. However, to call methods, the Flex SWF must “know” about those methods; hence being strongly-typed. You’d then have to share the same class between SWF’s. While this wouldn’t be too bad, Flash CS3 broke exclude.xml, the ability to compile a SWF, but excluding certain classes from it. You did this so you could prevent compiling the same class into multiple child SWF’s that you knew would have the same class waiting for them in the parent.

Sanders commented on my past blog entry about this that there is apparently a way to get it to work. I haven’t read into it, but using intrinsics (namespace internal) seems a valid solution. Using JSFL, it’s also tons easier to create code generating and others tools for Flash than it is for Flex and ANT. Then again, I haven’t tried Europa’s (Eclipse 3.2) JavaScript API yet… me? Digressing? No way…

Dirk originally came up with the idea of using interfaces when loading Flash content into Flex. At the time, Flex was Flash Player 7 only, and Flash was at Flash Player 8. Flash Player 8 had all the new effect filters; Flex did not. Using interfaces, you could utilize BlurFilter for example via a SWF liaison; file uploading too.

The reason Interfaces are nice in this scenario is firstly because it’s small; it’s just a tincy class, usually less than 1k (micro-small in bytes when compiled to bytecode). Since you will be adding this interface to 2 or more SWF’s, it helps to lessen the damage. Secondly, it’s strongly typed, even in AS3. You cast things to Interfaces and even test if something implements an interface the same way you test to see if an instance is a class via:

trace ( cow is IBigPimpin ); // true

trace ( cow is ISpendinGeez ); // true

var rad : IUberYum = cow as IUberYum;

The steps for loading in a strongly-typed SWF are as follows:

  1. Create an Interface that both Flex and Flash will utilize.
  2. In Flash CS3, have your Document class implement that Interface.
  3. Compile your SWF (aka Test Movie).
  4. In Flex, load in the SWF.
  5. In the Event.COMPLETE handler, cast the result to the interface, and store it as a class member variable.

Here’s a sample interface that we use at work to handle a loaded Dart.swf. It loads pre-roll videos and ads (animated GIF’s or SWF’s). Notice the events… they give you code hinting in FlexBuilder for loaded SWF’s (Flex 3 only suckaz), woo WOO!

package com.multicastmedia.doubleclick.core

{

        import com.multicastmedia.doubleclick.events.DartEvent;        import flash.events.IEventDispatcher;

        [Event(name="gotCompanionAd", type="com.multicastmedia.doubleclick.events.DartEvent")]

        [Event(name="prerollDone", type="com.multicastmedia.doubleclick.events.DartEvent")]

        [Event(name="error", type="com.multicastmedia.doubleclick.events.DartEvent")]

        public interface IAdModule extends IEventDispatcher

        {

                function loadPreroll(adx:String,sz:String):void;

                function getCompanionAdURL():String;

                function getCompanionAdClickThrough():String;

                function setVolume(val:Number):void;

        }

}

…yes, I know the DartEvent is compiled into both SWF’s, HOWEVER, it is tincy, and in this case worth it since it’s needed.

Here’s some psuedo code to load the SWF into Flex:

// reference to the SWF so you can call methods on it later

var dartSWF:IAdModule;// this can be a SWFLoader in Flex instead, doesn't have to be Loader

var loader:Loader;

loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onComplete);

function onComplete ( event : Event )

{

        // once loaded, cast t3h SWF as an IAdModule

        dartSWF = loader.content as IAdModule;

}

The caveat to this, which I haven’t tested, is if you load your classes into a different ApplicationDomain. The only person on the planet I know who does this is me, so you don’t have to worry about it.

4 Replies to “Loading Random SWFs in a Strongly Typed Way”

  1. Hey Jesse, working on a Flex2 project where I’m building a very basic MVC architecture with plans that various views will be compiled Flex SWFs. Thanks for the article b/c it helps to see some of the basic code for your technique. Have any links to share for any limitations I might expect when we’re importing views dynamically that must communicate with instances of our MVC classes in the host container? So far, what I’ve read over time says there shouldn’t be any issues which makes sense since the bytecode all gets put into the same mem space as the Flash VM. However, I’m just trying to dig a little deeper now that I have to put this design into practice with a very large project. Thanks!

  2. Hey, do you know if we can make lightweight SWCs with the interface declarations and share them into Flash? Or, is just sharing the .as file the best way to go.

Comments are closed.