您的位置:首页 > 移动开发 > Objective-C

Flex数据绑定陷阱(三)

2010-08-10 15:08 375 查看
Using binding in place of direct assignment
在直接赋值的地方使用绑定


有一种情况,就是你可以不使用绑定,使用直接赋值就可以成功实现同样效果的话,你最好不要使用绑定。
我已经看到过很多形式的这类型错误了。

下面的代码就可以说明:

<?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"

   minWidth="1024" minHeight="768">                        

   <fx:Script>

      <![CDATA[

         private var text:String;

      ]]>

   </fx:Script>                        

   <s:layout>

      <s:VerticalLayout/>

   </s:layout>

                           

   <s:TextInput id="textInput2" text="{text}"  />

</s:Application>

复制代码
这段代码中定义了一个文本输入框,将私有成员变量绑定 到这个文本输入框的text属性上。
它看起来无害,对不对?我经常看到Flex应用程序中使用这些类型的标签。
Flex的编译器会自动生成代码来实现绑定。
你会发现,尽管你不需要绑定text字符串,因为它是一次性赋值的,但是编译器仍然会生成代码,来适应属性绑定的条件。
另外,有些情况下你需要在赋值后解除绑定,或是移出绑定代码来减少开销,但是你在MXML中使用<mx:Binding> 标签后将不能这样做。

作为一个经验法则,应避免使用绑定到一个私有变量。

在上面的例子中,你可以直接给输入文本框设置值。

<s:TextInput id="textInput2" text="some text goes here" />

当你使用直接赋值时,你会大大减少你的开销,因为编译器不再会生成你不需要的绑定代码。

作为一个通用的经验法则,不要使用数据绑定,除非你绑定的值可能或肯定会改变。

Forgetting to unbind and risking memory leaks
忘记取消绑定和内存泄漏风险


You can use the <mx:Binding> tag in MXML or curly braces to easily implement binding;
however, there is overhead associated with these methods.
Additionally, you cannot unbind properties using these techniques.
If you are optimizing a high-performance application, you can use the BindingUtils class to bind your objects.  
There are two ways to use the BindingUtils class:

你可以在MXML文件中使用<mx:Binding>标 签,或者使用花括号来轻松实现绑定;
尽管如此,这些方法都会产生开销。
除此之外,你不能使用这些方法来取消绑定。
如果你希望优化你的程序,你可以使用BindingUtils类来绑定你的对象。
这里有两种使用BindingUtils类的方法:

    * The bindProperty() method is a static method used to bind a public property.
    * The bindSetter() method is a static method used to bind a setter function.
       
        *bindProperty()是一个静态方法,常常被用于绑定公共属性。
        *bindSetter()是一个静态方法,常常被用于绑定setter方法。

Take a look at the static bindProperty method signature:

先来看下bindProperty绑定属性方法的签名:

public static function bindProperty(


     site:Object, prop:String,


     host:Object, chain:Object,


     commitOnly:Boolean = false,


     useWeakReference:Boolean = false):ChangeWatcher

复制代码

The site and host parameters represent the destination and source objects respectively.
You set commitOnly to true when the handler is to be called only on committing change events;
set it to false (the default) when the handler is to be called on both committing and non-committing change events.

site和host参数分别代表目标对象和源对象。
commitOnly如果仅在提交 change 事件时需要调用处理函数,则设置为 true;如果无论是否提交 change 事件都调用处理函数,则设置为 false。默认值为false。

The useWeakReference parameter allows you to specify whether the reference to the host is strong or weak.
A strong reference (the default) prevents the host from being garbage-collected; a weak reference does not.
The example below includes a text input and a simple text component.  
When the TextInput control is preinitialized, preinitializeHandler() is called, which uses the bindProperty method.

useWeakReference使用弱引用参数允许你特别指定对源对象的引用是强引用还是弱引用。
强引用(默认值)阻止源对象被垃圾回收机制回收,而弱引用则相反。
下面的例子包含一个文本输入框和一个简单文本
当文本输入框被预初始化时,preinitializeHandler()被调用,在preinitializeHandler()方法里使用了 bindProperty方法。

<?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="1024" minHeight="768">

      <fx:Script>

         <![CDATA[

            import mx.binding.utils.BindingUtils;

            import mx.events.FlexEvent;

                                 

            protected function preinitializeHandler(event:FlexEvent):void

            {

               BindingUtils.bindProperty(label, "text", textInput, "text");

            }                                 

         ]]>

      </fx:Script>

   

      <s:layout>

         <s:VerticalLayout/>

      </s:layout>     

                  

      <s:TextInput id="textInput" preinitialize="preinitializeHandler(event)" />

      <s:Label id="label" />  

</s:Application>

复制代码
Here is the bindSetter method signature:
下面是bindSetter方法的签名:

public static function bindSetter(setter:Function, host:Object,


   chain:Object,

[b]   commitOnly:Boolean = false,


   useWeakReference:Boolean = false):ChangeWatcher

复制代码

The setter parameter specifies the setter method to invoke with an argument of the current value of chain when that value changes.
Here again, host represents the source object, and chain represents the property name.
The commitOnly and useWeakReference parameters work as with bindProperty.
setter参数指定一个setter方法,该方法会在chain指定的属性值改变时被调用,chain指定的属性的当前值会被作为该方法的一个参数传 入。
在这儿host也是指源对象,chain也是指属性名。
commitOnly和useWeakReference也和bindProperty方法中的作用一样。

Here is an example that uses bindSetter:
这儿是一个使用bindSetter方法的例子:

<?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="1024" minHeight="768">   

                           

   <fx:Script>

      <![CDATA[

         import mx.binding.utils.BindingUtils;

         import mx.events.FlexEvent;

         protected function preinitializeHandler(event:FlexEvent):void

         {

            BindingUtils.bindSetter(bindingSetter, textInput, "text");

         }

                                 

         private function bindingSetter(str:String):void

         {

            label.text = str;

         }                                 

      ]]>

   </fx:Script>

                       

   <s:layout>

      <s:VerticalLayout/>

   </s:layout>

                       

   <s:TextInput id="textInput" preinitialize="preinitializeHandler(event)" />

   <s:Label id="label" />

                        

</s:Application>

复制代码
Behind the scenes, the ChangeWatcher class is used in the BindingUtils class.
It allows weak references, so when you set useWeakReference to true the host will automatically be picked up by the garbage collector,
avoiding potential memory leaks.

在幕后,ChangeWatcher类被用于BindingUtils类。
它允许使用弱引用,因此当你设置useWeakReference参数为true时,host源对象会自动的被垃圾回收器回收,避免潜在的内存泄漏。

When you use weak references, the ChangeWatcher object needs to be unwatched after you are finished with it.
It is your responsibility to handle that task, which will ensure there are no memory leaks.  
The best way to handle that is to assign the static method returned by bindProperty to a ChangeWatcher variable
(since the static method returns a ChangeWatcher instance you can assign it to a variable).
When you do not need to bind the object anymore you can use the unwatch method, as you can see in the example below (see Figure 5).

当你使用弱引用时,你需要在使用完ChangeWatcher对象后对它调用unwatch()方法解除绑定。
完成这项任务是你的责任,这能确保不会出现内存泄漏。
最好的解决方法是将这个静态方法的返回值付给一个ChangeWatcher变量(因为这两个绑定的静态方法都返回一个ChangeWatcher类的实例,所以你可以将它们付给一个
ChangeWatcher类的变量)。
当你不再需要绑定这个对象时,对他使用unwatch()方法解除绑定,你可以在下面的例子中看到(看图5)。

<?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="1024" minHeight="768">

   <fx:Script>

      <![CDATA[

         import mx.binding.utils.ChangeWatcher;

         import mx.binding.utils.BindingUtils;

         import mx.events.FlexEvent;           

         private var change:ChangeWatcher;   

         protected function preinitializeHandler(event:FlexEvent):void

         {

            change = BindingUtils.bindProperty( label, "text",

            textInput, "text", false, true);

         }                                 

         protected function clickHandler(event:MouseEvent):void

         {

            change.unwatch();

            change = null;

         }                                 

      ]]>

   </fx:Script>

                       

   <s:layout>

      <s:VerticalLayout/>

   </s:layout>

   <s:TextInput id="textInput"

      preinitialize="preinitializeHandler(event)" />

   <s:Label id="label" />  

                     

   <s:Button label="Stop binding" click="clickHandler(event)" />

</s:Application>

复制代码
A simple application that uses the BindingUtils class and unbinds using a button
一个简单的应用,使用了BindingUtils类实现绑定,单击 按钮来解除绑定。



Figure 5 . A simple application that uses the BindingUtils class and unbinds using a button
图5. 一个简单的应用,使用了BindingUtils类实现绑定,单击按钮解除绑定。

The TextInput text property is binding to the Label text property,
and once you type text in the TextInput,
the data will be copied to the text property in the Label component.  
When you are ready to unbind, click Stop Binding.
This will unwatch the properties and set the object to null so it will be picked up during garbage collection.

这个文本输入框的text属性被绑定到Label标签的text属性上,
只要你在文本框中输入文本,内容会被复制到Label标签的text属性中。
当你准备解除绑定时,单击Stop Binding按钮。
这将会unwatch这个属性并将这个对象设为null,因此它会在垃圾回收时被回收。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息