Sometimes, when you build a Flex application, you encounter a compiler warning that says, “[Bindable] on a read-only getter is unnecessary and will be ignored.” If you’ve seen that message, and you’re curious what it means, hopefully I can explain it. In short, the compiler is telling you that it can’t actually make that property bindable because it has no way of determining when the property changes.
To understand that better, you should first know a little more about how binding works. Normally, when you make a getter/setter pair bindable, the compiler adds a little extra code for you. Behind the scenes, it dispatches PropertyChangeEvent.PROPERTY_CHANGE to tell the binding system that your property has changed. Basically, it converts your property functions from something like this:
private var _example:String = "I am the very model of a modern Flex developer";
[Bindable]
public function get example():String
{
return this._example;
}
public function set example(value:String):void
{
this._example = value;
}
to this:
private var _example:String = "I am the very model of a modern Flex developer";
[Bindable("propertyChange")]
public function get example():String
{
return this._example;
}
public function set example(value:String):void
{
this._example = value;
this.dispatchEvent(new PropertyChangeEvent(PropertyChangeEvent.PROPERTY_CHANGE);
}
If you don’t have a setter, there’s nowhere for the compiler to act smart and determine that your property has changed. If you want a getter without a setter to be bindable, you need to specify an event to be fired when the value returned by the getter changes. Your code should look something like this:
private var _example:String = "I am the very model of a modern Flex developer";
[Bindable("exampleChange")]
public function get example():String
{
return this._example;
}
Notice the inclusion of the event type in the metadata’s parentheses.
That’s only the first part, though. Next, you need to actually dispatch the exampleChange event from somewhere in your code. For example, let’s say that we change the _example variable when an URLLoader returns a result:
private function urlLoader_completeHandler(event:Event):void
{
var loader:URLLoader = URLLoader(event.currentTarget);
loader.removeEventListener(Event.COMPLETE, completeHandler);
this._example = loader.data.toString();
this.dispatchEvent(new Event("exampleChange"));
}
Any time you change _example, you need to dispatch the exampleChange event specified in the metadata so that the the binding system knows about what you did. If you set _example in many different places, you might consider making a private or protected setter that sets _example and dispatches that event, but that’s not required.
In summary, the compiler warning goes away when you specify an event type in the metadata. Simply specifying an event type won’t update bindings though, you also have to dispatch that event when the underlying variable changes. When the binding system receives your event, it knows to update any component to which your getter is bound.
One extra thing worth mentioning is that any property with Bindable metadata that has no event specified with dispatch the same generic propertyChange event. This means the binding system will have to work harder than needed because it could receive the same event for many different properties. It’s a good idea to a create custom event for each property to avoid this limitation. You can see in the Flex framework source code that Adobe has separate events for most, if not all, bindable properties they create.
