我有一个View类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:无法访问空对象引用的属性或方法。 at cafeparsley.view :: EmployeeList / _EmployeeList_List1_i()[C:\ dev \ code \ workspace \ Examples \ CafeParsley \ src \ cafeparsley \ view \ EmployeeList.mxml:29] at 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.x \ frameworks \ projects \ spark \ src \ spark \ components \ SkinnableContainer.as:827] 在mx.core :: UIComponent / initialize()[E:\ dev \ 4.x \ frameworks \ projects \ framework \ src \ mx \ core \ UIComponent.as:7349] 在mx.core :: UIComponent / http://www.adobe.com/2006/flex/mx/internal :: childAdded()[E:\ dev \ 4.x \ frameworks \ projects \ framework \ src \ mx \芯\ UIComponent.as:7241] 在mx.core :: UIComponent / addChildAt()[E:\ dev \ 4.x \ frameworks \ projects \ framework \ src \ mx \ core \ UIComponent.as:6947] 在spark.components :: Group / addDisplayObjectToDisplayList()[E:\ dev \ 4.x \ frameworks \ projects \ spark \ src \ spark \ components \ Group.as:1825] 在spark.components :: Group / http://www.adobe.com/2006/flex/mx/internal :: elementAdded()[E:\ dev \ 4.x \ frameworks \ projects \ spark \ src \ spark \组件\ Group.as:1416] 在spark.components :: Group / setMXMLContent()[E:\ dev \ 4.x \ frameworks \ projects \ spark \ src \ spark \ components \ Group.as:512] 在spark.components :: Group / set mxmlContent()[E:\ dev \ 4.x \ frameworks \ projects \ spark \ src \ spark \ components \ Group.as:452] 在spark.components :: SkinnableContainer / set mxmlContent()[E:\ dev \ 4.x \ frameworks \ projects \ spark \ src \ spark \ components \ SkinnableContainer.as:604] 在spark.components :: SkinnableContainer / createDeferredContent()[E:\ dev \ 4.x \ frameworks \ projects \ spark \ src \ spark \ components \ SkinnableContainer.as:986] 在spark.components :: SkinnableContainer / createContentIfNeeded()[E:\ dev \ 4.x \ frameworks \ projects \ spark \ src \ spark \ components \ SkinnableContainer.as:1014] 在spark.components :: SkinnableContainer / createChildren()[E:\ dev \ 4.x \ frameworks \ projects \ spark \ src \ spark \ components \ SkinnableContainer.as:827] 在spark.components :: NavigatorContent / createChildren()[E:\ dev \ 4.x \ frameworks \ projects \ spark \ src \ spark \ components \ NavigatorContent.as:225] 在mx.core :: UIComponent / initialize()[E:\ dev \ 4.x \ frameworks \ projects \ framework \ src \ mx \ core \ UIComponent.as:7349] at cafeparsley.view :: EmployeeList / initialize()
因此,抛出错误时employeeListPM为null。但是,如果我评论出来的话
<s:List>
组件,在init方法中重新运行并设置断点,init()将被调用。因此,我的上下文配置不是错误的,只是PM没有及时注入并且错误被抛出。但根据Parsley手册,如果我使用自动装配或<parsley:configure/>
PM应该在需要时注入。
在我认为相对琐碎的依赖注入场景中,我看不出我做错了什么。你能帮忙吗?
答案 0 :(得分:1)
这里有几点:
您的示例不包含<Configure />
或<FastInject />
标记,但是因为您在帖子中提到它们,我会假设它们只是从示例代码中丢失了。 (如果没有,那么你需要添加其中一个才能工作)。
但是,更有可能的是,您的代码中存在竞争条件。
具体来说,这些行:
labelFunction="model.properName"
change="model.initUpdateEmployee(empList.selectedItem);empList.selectedIndex = -1;"
Model
是一个注入属性,但是不能保证在代码首次运行时注入。
相反,将代码移动到执行空检查的类中的脚本中,然后将逻辑推迟回PM。
即:
labelFunction="nameFunction"
private function nameFunction(item:Object):String
{
return (model) ? model.properName(item) : "";
}
答案 1 :(得分:0)
要考虑的另一件事是你从用Parsley [Init]元标记标记的View函数调用model.init()。我建议你将相同的[Init]元数据应用于Model的init()方法。
[Init]
public function loadEmployees():void {
employeeService.loadEmployees( this );
}
这样做而不是从视图中调用model.init()。尽管生命周期文档声明:
在实例化对象并处理完所有注入后,将调用标记为[Init]的方法。
我有更多一致的结果,不直接在注入的对象之间调用任何init()方法,而是使用元数据标记方法。