Apache flex Flex: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

我认为我遗漏了FlexSDK组件生命周期中的一些重要内容,但我无法对其进行分类,尽管我阅读了很多教程。请分享您的经验,了解如何操作flex visual object的属性,以及在组件创建完成之前访问它们时如何避免NPE。 假设我们有一个简单的组件MyTitleWindow.mxml:

当然,行myTitleWindow.myDataGrid.dataProvider=data将抛出一个NPE,因为我们正在尝试访问尚未呈现的myDataGrid

目前我只能看到两种避免NPE的方法:

  • 为titleWindow中的数据创建一个setter,将数据放入 隐藏物侦听creationComplete事件,在其处理程序中应用数据 从缓存到数据网格。这种方法很管用,但我很抱歉 厌倦了在整个应用程序中添加此安全防护
  • 制造 可绑定属性-仅适用于简单数据类型 (数字、字符串…)

  • 在使用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));
    }