Data Binding Will Not Be Able To Detect Assignments To Sharpen

Requirements 

   
Prerequisite knowledge

Some knowledge of Flex and ActionScript is needed.

 

Required products

Flex (Download trial)

 
User level  

Intermediate

   

 

Missing silent errors

There are cases where the binding operation just does not seem to work, and you end up frustrated and unsure of what to do.

 

Exceptions and errors that are thrown by binding expressions, or in binding functions called within the binding framework, are silently captured. As a result, you will not see a runtime exception as you might expect in the debug version of Flash Player.  Not only does the binding not work, but no errors are shown.

 

 

Why are errors being silently captured?
The code that implements the binding mechanism requires several conditions to be met before the binding will occur. The binding mechanism will swallow any errors to prevent runtime exceptions from being thrown at runtime. This is a good thing since you do not want to see these (possibly) unexpected errors in your application.

 

Consider the following simple binding example:

 

I have added an variable binding to a Label component.  The code would have worked fine; however, I have set the variable to during the pre-initialization of the component. The event was dispatched at the beginning of the component initialization sequence, so the Label component was not set yet. The variable gets set to , so there is no property on the object.  If you run this application, you'll notice that binding does not occur and the errors have been silently captured. 

 

Although errors are captured silently, there are still things you can do to figure out what is going on.  Debugging with the and code is not easy  since the binding classes are not available to you unless you download the entire Flex SDK. 

 

Instead, you can set a break point and drill down to the related binding objects to find out what went wrong.  In this case, you would find that the value of the XML object is set to , and that is why the binding has failed (see Figure 1).

 

Figure 1. The value of the XML object is set to null

Another approach, which is more intuitive, is to use the method in the BindingManager class.  You set the component and property you want to watch, and then you can see the errors that were fired and silently captured.

 

In the example code above I left the following line of code commented:

 

Figure 2. Binding errors in the console

Take a look at the Binding.as and BindingManager.as classes. The code has many and statements that ensure conditions are met for performing a valid binding. Here are some of the error cases that can be thrown when using binding:

 

  • Error #1006: Call attempted on an object that is not a function.
  • Error #1009: Null has no properties.
  • Error #1010: Undefined has no properties.
  • Error #1055: Has no properties.
  • Error #1069: Property - not found on - and there is no default value
If any of these errors occur, the binding manager catches them silently and will not perform the binding.  You will be able to see them using the debug option of the binding manager. The binding manager captures other errors in addition to these.

 

Runtime errors can occur normally in many scenarios. For example, when a Label component is initialized that contains a data binding expression, the target property may not yet be set and execution of the binding expression will result in an Error #1009 – Null has no properties runtime exception. Similarly, some data binding expressions are only valid when the user of your application performs an action such as selecting an item in a List. If your data binding expression references the selectedItem property of the List, it will be null until the user actually clicks an item in the List and selects it.

 

 

Trying to bind a class that does not include the IPropertyChangeNotifier interface

Figure 3. UIComponent class signature

Because the code is trying to bind a class that does not implement , the binding mechanism will not work.

 

In this case, you'll see the following message in the Problems view (see Figure 4):

 

Figure 4. The Problems view shows warning messages

 

The ObjectProxy class
Data binding requires that the class to which you are binding implements the interface. Otherwise, the object is not bindable.

 

However, classes/properties or variables, such as primitive variables, that are not marked [Bindable] do not implement that interface. If it is your own class, all you have to do is add the [Bindable] metadata tag. If it's not your class you wish to bind with, or you want to add binding functionality during runtime you can use the class. wraps a non-bindable class and dispatches a PropertyChangeEvent when any of the properties of the class are changed, enabling objects in your application to listen for property changes. See ObjectProxy in the Adobe Flex 4 Language Reference for more information.

 

Below is an example of using . I create a new instance of and pass the object I want to watch, in this case . I then add an event listener and track changes to an item in .

 

 

Using binding in place of direct assignment

In situations where you do not need to bind and you can achieve the same effect with direct assignment, then it is best to avoid binding.  I have seen this type of mistake in many shapes and forms.

 

The code below illustrates one example:

 

The code defines a TextInput control with a property binding to the private variable.  It looks harmless enough, right?  I have seen these types of tags often in Flex applications.  The Flex compiler generates code to allow the binding.  You will find that although you do not need to bind the String since it is a one-time assignment, the compiler still generates code to accommodate binding of the property.   Additionally, there are cases where you want to unbind after the assignment or remove the binding code to reduce overhead, but you will not be able to do so using the tag in MXML.

 

 

As a rule of thumb, avoid using binding to a private variables.

In the example above you can use direct assignment to set the value:

 

When you use direct assignment, you significantly reduce your overhead because the compiler does not create unnecessary binding code. 

 

As a general rule of thumb, do not use data binding unless the property to which you are binding can or will change.

 

 

Forgetting to unbind and risking memory leaks

You can use the 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 class:

 

  • The method is a static method used to bind a public property.
  • The method is a static method used to bind a setter function.
Take a look at the static method signature:

 

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

 

The 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, is called, which uses the method.

 

The parameter specifies the setter method to invoke with an argument of the current value of when that value changes. Here again, represents the source object, and represents the property name. The and parameters work as with .

 

Here is an example that uses :

 

Behind the scenes, the class is used in the class. It allows weak references, so when you set to the will automatically be picked up by the garbage collector, avoiding potential memory leaks.

 

When you use weak references, the 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 to a variable (since the static method returns a instance you can assign it to a variable). When you do not need to bind the object anymore you can use the method, as you can see in the example below (see Figure 5).

 

Figure 5 . A simple application that uses the BindingUtils class and unbinds using a button

 

Not changing the default propertyChange event constant

When you use the tag without adding an event setting, is the default event type that will be dispatched. So a tag is equivalent to .  The compiler creates additional code for the setter and getter when you do not specify the event string, so it is recommended that you add your own name constant to avoid this extra overhead.

 

Consider the following binding statement:

 

As you can see the mxmlc creates a generated setter which contains code that dispatches the . When you change the default constant, the Flex compiler will NOT generate code and you are responsible for dispatching the event yourself. This allows you to optimize the listening code. If you don't change the default constant, every [Bindable] property will dispatch the event and the listening code must interrogate the event to determine exactly which property changed. This is especially costly process if a class has a large number of [Bindable] properties.

 

Once you set the event name yourself, such as in the example below, the compiler just copies the code over.

 

 

Using the wrong bindable event name

The code above assigns a static property to the event name, and then uses the same assignment to dispatch the event. However, when the value changes, the binding does not appear to work.  The reason is that the event name will be and not the value of the variable.

 

The code should have been written as follows:

 

 

Assuming an execution order for binding

A common mistake when binding is assuming that binding occurs in a synchronous execution order. This can cause your application to generate warnings and not bind your property.  Events in ActionScript are executed in an asynchronous manner. 

 

Take a look at the example below:

 

Figure 6. A compile time warning is shown in the Problems view.

Below is another example. It assumes that the value of the first control is already set.  This type of assignment also causes the compiler to generate all the code needed for binding.  You have to decide if that code is needed or if a direct assignment () is a better choice.

Data binding—the process of passing the data in one object to another object automatically—is one of the most used and useful features when building Flex and Adobe AIR applications. At the same time, however, data binding can slow application initialization and cause frustration when developers don't fully understand how the mechanism works.  It is a good idea to make sure you are using it correctly and only when needed.  In this article, I've compiled a list of ten common pitfalls and mistakes that developers are susceptible to when building an application that uses data binding.

 

Uncomment this line and run the application in debug mode; you can see the binding errors in the Console view (see Figure 2).

 

Classes that implement the marker interface must dispatch events for properties in the class, and any nested classes are publicly exposed as properties.  As a result, you can find out when properties have changed in the class.  For instance, take a look at the UIComponent class signature (see Figure 3).  indeed implements , which will dispatch an event once properties have changed.

 

Now consider the following class that holds user information:

 

If you try to bind the text property of a Label to one of the properties of the UserInfo class, it will not work, as illustrated below:

 

To allow data binding to work in the previous example, you can attach the tag to the class. This will enable all public properties of the class for data binding. The Flex compiler will generate a public getter and setter for you which will contain all of the code necessary to make data binding work. Alternatively, you can attach the tag to specific properties of the class if you don't want to enable all properties for data binding.

 

One thing to keep in mind when using is that in order to facilitate assignment notification, registered listeners will be invoked every time any property on the target object changes. That can potenielly introduce a significant overhead, in fact in our example the is called twice since two changes occurred.

 

Here is the method signature:

 

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

 

Because no event name was set, the compiler will create the following:

 

Using the wrong event name in the tag can cause your application to not bind your property, and you will not even know why.  When you use the tag with a custom name, the example below looks like a good idea:

 

The code above may work; however, it may not.  It assumes that the property was already set since the value of in the button component is binding to the property.  If you compile this application you'll also get a compile time warning (see Figure 6).

 

Затем подошла еще одна группа, и жертва окончательно исчезла из поля зрения Халохота. Кипя от злости, тот нырнул в стремительно уплотняющуюся толпу. Он должен настичь Дэвида Беккера. Халохот отчаянно пытался протиснуться к концу улочки, но внезапно почувствовал, что тонет в этом море человеческих тел.

Со всех сторон его окружали мужчины в пиджаках и галстуках и женщины в черных платьях и кружевных накидках на опущенных головах.

One thought on “Data Binding Will Not Be Able To Detect Assignments To Sharpen

Leave a Reply

Your email address will not be published. Required fields are marked *