views:

71

answers:

1

Hi:

I have a Main class loading 2 SWF (loader and viewer, also with document classes). They need to share a double buffer with content, of course, filled by loader and showed by viewer

I was thinking to use the LocalConnection class but after a suggestion from PatrickS now I'm evaluating the possibility of a Singleton Class. I've never used this pattern in AS and must confess I'm rather biased against it. But in this particular case I guess it'll be useful. By the way, a little bit surprised reading in the gskinner blog 2 implementations examples. So, I'll really appreciate your views, knowing this subject is an endless war like the Mac vs PC one

Take into account: 1. AIR desktop application running 24x7 during some months in a high-end Windows PC. No user interaction 2. High performance code is a must because content loaded are full HD images

My other concern is about memory leaks

Thanks in advance

+1  A: 

I'd avoid a Singleton, personally, as its regularly implemented. However, having a single instance of this buffer object makes sense. So what I'd do in this case is have your Main class created this object. When the viewer is loaded, pass it this object. Then do the same for the loader. Now, both of your swfs share a common object that they could use to communicate. Then you can call functions on it and make it dispatch events if you want (extending EventDispatcher or implementing IEventDispatcher). Or you can just register callbacks if you want (should be a bit faster, but not sure if it will make a big difference).

Edit

Having a look at your other question I think your problem was related to getting the right loader and passing data to the loaded content. Here's an skecth of how you could implement what I mentioned above.

PhotoLoader.swf:

package  {
import flash.display.Sprite;
import flash.events.Event;

public class PhotoLoader extends Sprite {

    private var _commonObject:CommonObject;

    public function PhotoLoader() {

    }

    public function setCommonObject(commonObject:CommonObject):void {
        trace("PhotoLoader::setCommonObject", commonObject);
        _commonObject = commonObject;
        _commonObject.addEventListener(Event.INIT,handleInit);
    }

    private function handleInit(e:Event):void {
        trace("PhotoLoader::handleInit");
    }

}

} 

PhotoViewer.swf:

package  {
    import flash.display.Sprite;
    import flash.events.Event;

    public class PhotoViewer extends Sprite {

        private var _commonObject:CommonObject;

        public function PhotoViewer() {

        }

        public function setCommonObject(commonObject:CommonObject):void {
            trace("PhotoLoader::setCommonObject", commonObject);
            _commonObject = commonObject;
            _commonObject.addEventListener(Event.INIT,handleInit);
        }

        private function handleInit(e:Event):void {
            trace("PhotoViewer::handleInit");
        }

    }

}

Main.swf

package {
    import flash.display.Loader;
    import flash.display.LoaderInfo;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.net.URLRequest;
    import flash.system.ApplicationDomain;
    import flash.system.LoaderContext;

    public class Main extends Sprite {

        private var _photoLoader:PhotoLoader;
        private var _photoViewer:PhotoViewer;
        private var _commonObject:CommonObject;

        private var _viewerLoader:Loader;
        private var _loaderLoader:Loader;

        private var _count:int = 0;

        public function Main():void {
            _commonObject = new CommonObject();
            loadSwfs();

        }

        private function loadSwfs():void {

            _viewerLoader = new Loader();
            _viewerLoader.contentLoaderInfo.addEventListener(Event.INIT,handleInit);
            _viewerLoader.load(new URLRequest("PhotoViewer.swf"));

            _loaderLoader = new Loader();
            _loaderLoader.contentLoaderInfo.addEventListener(Event.INIT,handleInit);
            _loaderLoader.load(new URLRequest("PhotoLoader.swf"));

        }

        private function handleInit(e:Event):void {
            trace("handleInit");
            var loader:Loader = (e.target as LoaderInfo).loader;
            switch(loader) {
                case _viewerLoader:
                    _photoViewer = _viewerLoader.content as PhotoViewer; 
                    _photoViewer.setCommonObject(_commonObject);
                    _count++;
                    break;
                case _loaderLoader:
                    _photoLoader = _loaderLoader.content as PhotoLoader; 
                    _photoLoader.setCommonObject(_commonObject);
                    _count++;
                    break;
            }
            if(_count == 2) { 
                _commonObject.init();
            }

        }


    }

}

And the common object, shared by the 3 swf:

package  {
    import flash.events.Event;
    import flash.events.EventDispatcher;

    public class CommonObject extends EventDispatcher {

        public function CommonObject() {

        }

        public function init():void {
            dispatchEvent(new Event(Event.INIT));
        }
    }

}

Basically when you load both your viewer and loader swfs you pass an instance of this common object. Then you register to listen for an INIT method: this will tell loader and viewer that everything has been setup. So at this point you can start sending messages from your viewer or loader to the other party (you could implement this through event dispatching); basically make a method in the common object to do it for you or just call dispatchEvent on the common object directly.

Juan Pablo Califano
JP: thanks a lot for your help, your code seems clean and easy to implement so, I'll give a try (just a little thing, it seems you forgot to import CommonObject class in Main.as, no?). And a question, when you say I'd avoid a Singleton, personally, as its "regularly" implemented, what exactly do you mean? Bad code, never use a design pattern if it isn't natively implemented in the language, ...? Implementations in Grant Skinner's blog, Apple AS3 documentation or this site looks pretty straightforward
hsands
@hsands. You're welcome. The import is not necessary if the classes are in the same package. Since this is just test code, I put everything in the "global" package. In a real project, though, you might want to put your code in a package to avoid name collisions.
Juan Pablo Califano
@hsands. Re singletons: sometimes it makes sense to have only one instance. I don't like how the pattern tries to enforce this: having a static accesor that creates / retrieves this instance. I'd rather create this instance somewhere else and pass it along (kind of like dependecy injection). Because, for one thing, if your object needs to take parameters, this pattern becomes inconvenient. Also, if you have more than one appDomain, you could end up with multiple instances (this will not be so obvious when you read the code). And if you ever need to create another instance, you're in trouble.
Juan Pablo Califano
hsands
@hsands. No problem. Check out this for an introduction to custom events. http://www.learningactionscript3.com/2008/11/11/passing-arguments-with-events/. Extending `Event` is rather simple (don't forget to override the `clone()` method!), so I think taking a look of some sample code, you'll get the idea. It's just a tiny bit of syntax (the rest is designing what data you want to pass around, which is up to you). If you find some trouble, though, don't hesitate to open a new question.
Juan Pablo Califano