Apache flex Flex:NPE和在创建完成之前访问组件属性的正确方法
我认为我遗漏了FlexSDK组件生命周期中的一些重要内容,但我无法对其进行分类,尽管我阅读了很多教程。请分享您的经验,了解如何操作flex visual object的属性,以及在组件创建完成之前访问它们时如何避免NPE。 假设我们有一个简单的组件MyTitleWindow.mxml: 当然,行myTitleWindow.myDataGrid.dataProvider=data将抛出一个NPE,因为我们正在尝试访问尚未呈现的myDataGrid 目前我只能看到两种避免NPE的方法:Apache flex Flex:NPE和在创建完成之前访问组件属性的正确方法,apache-flex,flex4,flex3,Apache Flex,Flex4,Flex3,我认为我遗漏了FlexSDK组件生命周期中的一些重要内容,但我无法对其进行分类,尽管我阅读了很多教程。请分享您的经验,了解如何操作flex visual object的属性,以及在组件创建完成之前访问它们时如何避免NPE。 假设我们有一个简单的组件MyTitleWindow.mxml: 当然,行myTitleWindow.myDataGrid.dataProvider=data将抛出一个NPE,因为我们正在尝试访问尚未呈现的myDataGrid 目前我只能看到两种避免NPE的方法: 为title
在使用flex验证/失效周期方面,我有没有遗漏什么可以帮助避免过多代码的地方?是的,这可能是一个麻烦,而且不仅仅是弹出窗口。当使用带有默认creationpolicy的ViewStack组件时,这也可能是一个难题,我经常这样做 我可能会因此被激怒,但我通常只使用绑定。我不确定你所说的“简单数据类型”是什么意思——它也适用于自定义类型。你必须提供一个例子 您可以做的一件事(我可能会为此而大发雷霆:p)是尽早创建弹出组件实例并重用它,而不是每次都创建一个新实例
不,我不认为您在组件生命周期中“遗漏了什么”。是的,这可能是一个麻烦,而且不仅仅是弹出窗口。当使用带有默认creationpolicy的ViewStack组件时,这也可能是一个难题,我经常这样做 我可能会因此被激怒,但我通常只使用绑定。我不确定你所说的“简单数据类型”是什么意思——它也适用于自定义类型。你必须提供一个例子 您可以做的一件事(我可能会为此而大发雷霆:p)是尽早创建弹出组件实例并重用它,而不是每次都创建一个新实例
不,我不认为您在组件生命周期中“遗漏了什么”。您和Crusader报告的问题是因为在Flex中,组件是惰性初始化的。这通常是一件好事,但在你的情况下,正是这件事导致了你的问题 一般来说,我不建议从组件外部设置视图组件上的dataProvider,因为您无法知道是否已设置好并准备好使用 我通常做的事。在简单的情况下,我只是简单地添加一个公共属性,使之成为[可绑定的]。(我认为)更干净的方法是创建一个setter(和getter),然后将数据提供程序保存在一个局部变量中(在您的例子中可能是ArrayCollection)。在setter中,我通常检查“myDataGrid”是否存在,如果存在,则另外设置dataProvider属性。然后,我会在我的组件中添加一个CreationComplete回调,并在其中设置dataProvider 因此,当在组件完成初始化之前设置dataProvider时,该值将简单地保存在局部变量中,并在完成设置后自动设置dataProvider。如果组件是allready设置(您正在更改数据提供程序),则设置程序将自动更新“myDataGrid”的数据提供程序
...
私有var myDataProvider:ArrayCollection;
私有函数onCreationComplete(事件:FlexEvent):void{
myDataGrid.dataProvider=myDataProvider;
}
公共函数集myDdataProvider(myDataProvider:ArrayCollection):void{
myDataProvider=myDataProvider;
//仅在网格可用时更新数据提供程序。
if(myDataGrid){
myDataGrid.dataProvider=myDataProvider;
}
}
....
您和Crusader报告的问题是因为Flex中的组件初始化为惰性。这通常是一件好事,但在你的情况下,正是这件事导致了你的问题
一般来说,我不建议从组件外部设置视图组件上的dataProvider,因为您无法知道是否已设置好并准备好使用
我通常做的事。在简单的情况下,我只是简单地添加一个公共属性,使之成为[可绑定的]。(我认为)更干净的方法是创建一个setter(和getter),然后将数据提供程序保存在一个局部变量中(在您的例子中可能是ArrayCollection)。在setter中,我通常检查“myDataGrid”是否存在,如果存在,则另外设置dataProvider属性。然后,我会在我的组件中添加一个CreationComplete回调,并在其中设置dataProvider
因此,当在组件完成初始化之前设置dataProvider时,该值将简单地保存在局部变量中,并在完成设置后自动设置dataProvider。如果组件是allready设置(您正在更改数据提供程序),则设置程序将自动更新“myDataGrid”的数据提供程序
...
私有var myDataProvider:ArrayCollection;
私有函数onCreationComplete(事件:FlexEvent):void{
myDataGrid.dataProvider=myDataProvider;
}
公共函数集myDdataProvider(myDataProvider:ArrayCollection):void{
myDataProvider=myDataProvider;
//仅在网格可用时更新数据提供程序。
if(myDataGrid){
myDataGrid.dataProvider=myDataProvider;
}
}
....
我总是试图将设置数据提供程序的责任倒置
,并希望组件遵守
<s:TitleWindow>
<s:DataGrid id="myDataGrid" />
</s:TitleWindow>
private function handleDataReceived(data : ArrayCollection) : void {
var myTitleWindow : TitleWindow = new MyTitleWindow();
PopUpManager.addPopUp(myTitleWindow);
myTitleWindow.myDataGrid.dataProvider = data;
}
<s:TitleWindow creationComplete="onCreationComplete(event)">
...
private var myDataProvider:ArrayCollection;
private function onCreationComplete(event:FlexEvent):void {
myDataGrid.dataProvider = myDataProvider;
}
public function set myDdataProvider(myDataProvider:ArrayCollection):void {
myDataProvider = myDataProvider;
// Only update the dataProvider if the grid is available.
if(myDataGrid) {
myDataGrid.dataProvider = myDataProvider;
}
}
....
<s:DataGrid id="myDataGrid" />
</s:TitleWindow>
<s:TitleWindow>
<s:DataGrid dataProvider="{data}" />
</s:TitleWindow>
public static function withData(data : ArrayCollection) : MyTitleWindow
{
var myTitleWindow : MyTitleWindow = new MyTitleWindow();
myTitleWindow.data = data;
return myTitleWindow;
}
private function handleDataReceived(data : ArrayCollection) : void
{
PopUpManager.addPopUp(MyTitleWindow.withData(data));
}