分配跨越SWF边界的类型变量会中断

时间:2012-01-29 21:20:02

标签: flash actionscript-3 flash-cs5 document-class

我正在编写一个使用可扩展UI元素的应用程序,其精确实现是在运行时使用配置确定的。因此,例如,我想显示一个项目列表,根据配置,可以显示为项目符号列表,编号列表,两列列表等。包含应用程序对具体实现一无所知,除了它是一种支持方法调用setItems(items:Array):void的类型。

所以我设置了一个基类,例如:

package my.stuff {
    public class BaseList extends MovieClip {
        protected var m_items:Array;
        public function BaseList() {
            m_items = new Array();
        }
        public function setItems(items:Array):void {
            for (var i:int = 0; i < items.length; i++)
                m_items.push(items[i]);
        }
    }
}

然后我创建了一个专门的实现,例如,两列列表:

package my.stuff {
    public class TwoColumnList extends BaseList {
        protected var m_columns:Array;
        public function TwoColumnList() {
            super();
            m_columns = new Array();
            m_columns.push(new Array());
            m_columns.push(new Array());
        }
        public override function setItems(items:Array):void {
            for (var i:int = 0; i < items.length; i++) {
                m_items.push(items[i]);
                m_columns[i%2].push(items[i]);
            }
        }
    }
}

现在,UI本身在Flash Professional中作为FLA完成,类TwoColumnList作为“文档类”。我将FLA(“发布”)编译到目标SWF,然后我尝试将其加载到应用程序中。通常情况下,我希望这样工作:

public function startLoading(implURL:String):void) {
    var loader:Loader = new Loader();
    loader.contentLoaderInfo.addEventListener(Event.INIT, doneLoadingImpl);
    loader.load(new URLRequest(implURL));
}

public function doneLoadingImpl(e:Event) {
    var info:LoaderInfo = e.target as LoaderInfo;
    var impl:DisplayObject = info.content;
    m_containerClip.addChild(impl);
    var listImpl:BaseList = impl as BaseList;
    impl.setItems(m_allItems);
}

除非这不起作用 - addChild()工作正常,但转化为BaseList会产生null(不是例外 - 仅null)。我可以将impl转换为MovieClip就好了,我也可以将它转发到TwoColumnList,之后它会很好地投射到BaseList,就像这样:

...
var listImpl:BaseList = impl as TwoColumnList;
...

这样可行,但它确实违背了整个练习的目的 - 这是提前知道将来可能创建的特定UI实现。

我在某处读过info.applicationDomain.getDefinition,但我不能说它会产生任何影响。

在我的日常工作中,我不是一名ActionScript开发人员,我刚刚被要求帮助一些主要开发人员不再与公司合作的项目,我很难过 - 任何帮助都将受到赞赏

1 个答案:

答案 0 :(得分:1)

您的问题很可能与加载到不同应用程序域的类有关。如果对象不是您要转换的类的子类,则类型转换返回null - 并且看起来您有两个版本的BaseList彼此“竞争”。

如果是这种情况,您可以通过将SWF显式加载到与主要应用程序域相同的应用程序域中来解决此问题:

 var ldrContext : LoaderContext = new LoaderContext ( false, ApplicationDomain.currentDomain );
 var loader:Loader = new Loader();
 loader.contentLoaderInfo.addEventListener(Event.INIT, doneLoadingImpl);
 loader.load(new URLRequest(implURL), ldrContext );

但是,特别是在加载外部内容时,您应该使用接口。保持实现分离正是它们的发明。查看this blog page,它解释了为什么在加载外部文件时应该使用接口(还有一个指向接口的更基本信息的链接),顺便说一句,作者似乎遇到了与你类似的问题......; )