0

我正在编写一个使用可扩展 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)。我可以很好地转换implMovieClip,我也可以将它的目录转换为TwoColumnList,然后它很好地转换为BaseList,如下所示:

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

所以这很有效,但它确实违背了整个练习的目的——即提前知道将来可能创建的特定 UI 实现。

我在某处读到过 doing info.applicationDomain.getDefinition,但我不能说它有任何效果。

在我的日常工作中,我不是 ActionScript 开发人员,我刚刚被要求帮助某个项目的主要开发人员不再在公司工作,我很难过 - 任何帮助将不胜感激。

4

1 回答 1

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 );

但是,尤其是在加载外部内容时,您确实应该使用接口。保持实现解耦正是它们的发明目的。查看这个博客页面,它解释了为什么在加载外部文件时应该使用接口(还有一个指向更多关于接口的基本信息的链接),顺便说一下,作者似乎遇到了和你类似的问题......;)

于 2012-01-29T23:08:34.057 回答