Flex懒惰绑定

Gur*_*ona 5 apache-flex binding lazy-loading

受Hibernate的延迟加载能力的启发,我希望仅在必要时使模型成为我的Flex UI请求数据的一部分.我认为这就像添加一个只在访问变量时才发送服务器请求的公共访问器一样简单.

public function get tab2AC():ArrayCollection
{
    if(_tab2AC == null){
        //Request data from server
    }
    return _tab2AC;
}
Run Code Online (Sandbox Code Playgroud)

问题是Flex似乎在应用程序启动时访问所有绑定变量,即使尚未创建引用组件.因此,即使dataProvider="{tab2AC}"尚未创建DataGrid ,服务器请求仍然会消失,从而打败"仅在需要时"懒惰.

我不想将服务器请求放在creationComplete处理程序中,因为我想让我的UI模型不知道视图状态和我的视图无视服务器请求.

有趣的是,如果我Alert.show("anything");在访问器中添加一个内部,它可以按需运行.

更新:这是一个完整的例子.设置断点,即使任何创建的组件都没有使用titleForScreen2,您也会看到Flex访问这两个变量.

<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
xmlns:s="library://ns.adobe.com/flex/spark" 
xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600">
<fx:Script>
    <![CDATA[
        private var _titleForScreen1:String;
        private var _titleForScreen2:String;

        public function get titleForScreen1():String {
            if(_titleForScreen1 == null){
                //Server Request
            }                   
            return _titleForScreen1;
        }

        public function get titleForScreen2():String {
            if(_titleForScreen2 == null){
                //Server Request
            }
            return _titleForScreen2;
        }
    ]]>
</fx:Script>

<mx:ViewStack>
    <s:NavigatorContent label="Screen 1">
        <s:Label text="{titleForScreen1}"/>
    </s:NavigatorContent>
    <s:NavigatorContent label="Screen 2">
        <s:Label text="{titleForScreen2}"/>
    </s:NavigatorContent>
</mx:ViewStack>
</s:Application>
Run Code Online (Sandbox Code Playgroud)

Gur*_*ona 0

是的,事情就是这样。由于 Flex 会立即评估绑定,因此我必须将绑定延迟到创建为止,以防止过早评估。似乎需要额外的工作来消除 Flex 的奇怪行为,但有时情况就是如此。

<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
xmlns:s="library://ns.adobe.com/flex/spark" 
xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600">
<fx:Script>
    <![CDATA[
        import mx.binding.utils.BindingUtils;
        import mx.binding.utils.ChangeWatcher;

        private var _titleForScreen1:String;
        private var _titleForScreen2:String;

        public function get titleForScreen1():String {
            if(_titleForScreen1 == null){
                //Server Request
            }
            return _titleForScreen1;
        }

        public function get titleForScreen2():String {
            if(_titleForScreen2 == null){
                //Server Request
            }
            return _titleForScreen2;
        }

        public function updateLabel1(value:String):void {screen1Label.text = value;}
        public function updateLabel2(value:String):void {screen2Label.text = value;}

        public function bindLabel1():void {
            var changeWatcher:ChangeWatcher = BindingUtils.bindSetter(updateLabel1,this, "titleForScreen1");
        }

        public function bindLabel2():void {
            var changeWatcher:ChangeWatcher = BindingUtils.bindSetter(updateLabel2,this, "titleForScreen2");
        }
    ]]>
</fx:Script>

<mx:ViewStack>
    <s:NavigatorContent label="Screen 1">
        <s:Label id="screen1Label" creationComplete="bindLabel1()"/>
    </s:NavigatorContent>
    <s:NavigatorContent label="Screen 2">
        <s:Label id="screen2Label" creationComplete="bindLabel2()"/>
    </s:NavigatorContent>
    </s:NavigatorContent>
</mx:ViewStack>
</s:Application>
Run Code Online (Sandbox Code Playgroud)