1

我有一个视图类 EmployeeList 如下:

<?xml version="1.0" encoding="utf-8"?>
<s:NavigatorContent xmlns:fx="http://ns.adobe.com/mxml/2009" 
                    xmlns:s="library://ns.adobe.com/flex/spark"
                    xmlns:parsley="http://www.spicefactory.org/parsley"
                    xmlns:mx="library://ns.adobe.com/flex/mx" width="400" height="300">


    <fx:Script>
        <![CDATA[
            import cafeparsley.model.EmployeeListPM;

            [Inject]
            [Bindable]
            public var model : EmployeeListPM;

            [Init]
            public function init () : void {
                model.init();
            }


        ]]>
    </fx:Script>    

    <s:Panel title="Employee List" horizontalCenter="0">
        <s:HGroup paddingTop="50">
            <s:Button label="Add New Employee" click="model.addNewEmployee()" />
            <mx:Spacer width="100%" />
            <s:Button label="Logout" click="model.logout()" />
            <mx:Spacer width="100%" height="20" />  
        </s:HGroup>
        <s:List id="empList" dataProvider="{ model.employees }" labelFunction="model.properName" 
                 change="model.initUpdateEmployee(empList.selectedItem);empList.selectedIndex = -1;" width="100%" />
        <s:Label id="error" color="0xFF0000" />
    </s:Panel>  

</s:NavigatorContent>

PM 看起来像这样:

package cafeparsley.model
{
    import cafeparsley.events.EmployeeEvent;
    import cafeparsley.events.NavigationEvent;
    import cafeparsley.services.impl.EmployeeServiceImpl;
    import cafeparsley.vo.Employee;

    import flash.events.EventDispatcher;

    import mx.collections.ArrayCollection;
    import mx.rpc.IResponder;

    [Bindable]
    [Event(name="navigationEvent", type="cafeparsley.events.NavigationEvent")]
    [ManagedEvents("navigationEvent")]
    public class EmployeeListPM extends EventDispatcher implements IResponder
    {

        public var employeeService : EmployeeServiceImpl = new EmployeeServiceImpl();

        public var employees : ArrayCollection;

        public function init() : void
        {
            loadEmployees();
        }


        public function EmployeeListPM() 
        {
        }

        public function loadEmployees():void
        {
            employeeService.loadEmployees( this );
        }  

无论我是使用还是自动装配来执行注入,当我运行它时,我都会收到以下错误消息:

TypeError:错误 #1009:无法访问空对象引用的属性或方法。在 cafeparsley.view::EmployeeList/_EmployeeList_List1_i()[C:\dev\code\workspace\Examples\CafeParsley\src\cafeparsley\view\EmployeeList.mxml:29] 在 cafeparsley.view::EmployeeList/_EmployeeList_Array2_c() 在 mx .core::DeferredInstanceFromFunction/getInstance()[E:\dev\4.x\frameworks\projects\framework\src\mx\core\DeferredInstanceFromFunction.as:105] 在 spark.components::SkinnableContainer/createDeferredContent()[E :\dev\4.x\frameworks\projects\spark\src\spark\components\SkinnableContainer.as:985] 在 spark.components::SkinnableContainer/createContentIfNeeded()[E:\dev\4.x\frameworks\projects \spark\src\spark\components\SkinnableContainer.as:1014] 在 spark.components::SkinnableContainer/createChildren()[E:\dev\4.

所以当错误被抛出时,employeeListPM 为空。但是,如果我注释掉 <s:List>组件,重新运行并在 init 方法中设置断点,init() 将被调用。所以不是我的上下文配置错了,只是PM没有及时注入,报错了。但是根据 Parsley 手册,如果我使用自动装配或<parsley:configure/>PM 应该在需要的时候注入。

在我认为是相对微不足道的依赖注入场景中,我看不出我做错了什么。你能帮我吗?

4

2 回答 2

1

这里有几点:

您的示例不包含<Configure />or<FastInject />标记,但是由于您在帖子中提到它们,我假设它们只是示例代码中缺少的。(如果没有,那么您需要添加其中之一才能使其正常工作)。

但是,更有可能的是,您的代码中存在竞争条件。

具体来说,这些行:

labelFunction="model.properName" 
change="model.initUpdateEmployee(empList.selectedItem);empList.selectedIndex = -1;"

Model是一个注入属性,但不能保证在代码第一次运行时已经注入。

相反,将代码移动到执行空检查的类中的脚本中,然后将逻辑推迟到 PM。

IE:

labelFunction="nameFunction"


private function nameFunction(item:Object):String
{
    return (model) ? model.properName(item) : "";
}
于 2011-09-08T22:31:15.193 回答
0

另一件要考虑的事情是,您正在从标有 Parsley [Init] 元标记的视图函数中调用 model.init()。我建议您将相同的 [Init] 元标记应用于模型的 init() 方法。

[Init]    
public function loadEmployees():void {
     employeeService.loadEmployees( this );
}

这样做而不是从视图中调用 model.init()。尽管生命周期文档指出:

标有 [Init] 的方法在对象被实例化并处理完所有注入后被调用。

我得到了更加一致的结果,没有直接在注入的对象之间调用任何 init() 方法,而是使用元数据标记方法。

于 2011-09-13T20:20:50.080 回答