######################################################
# Ministério da Saúde Adverte: Este post será bem maior do que o
# convencional e esta explicação sobre o funcionamento viciante
# do Data Binding pode fazer o seu cérebro entrar em loop.
######################################################
O [Bindable] é uma Metadata Tag o que significa dizer que é uma
instrução para o compilador fazer alguma coisa. Neste caso você está
falando para o compilador gerar o código necessário para sua
propriedade ser a fonte do DataBinding.
O segredo do funcionamento do DataBinding está na classe
"mx.binding.utils.ChangeWatcher". Esta classe se baseia em listeners
para fazer a "mágica" do DataBinding.
Tomemos o seguinte trecho de código abaixo para facilitar a
explicação:
<mx:TextInput id="tiSource"/>
<mx:TextInput id="tiDestination" text="{tiSource.text}"/>
Neste exemplo, toda vez que o usuário digitar algo no TextInput
"tiSource" isto será automaticamente copiado para o TextInput
"tiDestination".
Isto é possível porque a propriedade "text" é Bindable. Como tal, toda
vez que esta propriedade mudar ela distribuirá um evento - que neste
caso é chamado de "textChanged". Graças ao ChangeWatcher, que é usado
implicitamente toda vez que usamos as chaves {} para determinar o
Binding, será criado automaticamente um EventHandler para tratar este
evento "textChanged". A implementação deste EventHandler pegará o
valor do "text" de "tiSource" e copiará para o "text" de
"tiDestination".
Em outras palavras, a mágica do DataBinding é um código que é gerado
automaticamente pelo compilador do Flex que se baseia na arquitetura
Listener - Handler que já conhecemos: alguém distribui um evento e
alguém ouve para fazer alguma coisa. Neste caso uma propriedade muda,
e um código gerado automaticamente através de uma sintaxe predefinida
(chaves{}) copia o valor desta propriedade para outra.
Eu fiz um teste no Flex usando a opção keep-generated-
actionscript=true com uma propriedade Bindable e o resultado segue
abaixo.
Test.mxml
========
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="
http://www.adobe.com/2006/mxml"
width="100%" height="100%">
<mx:Script>
<![CDATA[
[Bindable]
private var myProp:String;
]]>
</mx:Script>
</mx:Application>
_Test-binding-generated.as (Código gerado pelo compilador Flex)
======================================================
class BindableProperty
{
[Bindable(event="propertyChange")]
private function get myProp():String
{
return this._1060147409myProp;
}
private function set myProp(value:String):void
{
var oldValue:Object = this._1060147409myProp;
if (oldValue !== value)
{
this._1060147409myProp = value;
dispatchEvent(mx.events.PropertyChangeEvent.createUpdateEvent(this,
"myProp", oldValue, value));
}
}
}
Ou seja, o usar o [Bindable] o compilador Flex gerou o arquivo "_Test-
binding-generated.as" cujo conteúdo pode ser visto acima. Observe que
no "set" da propriedade um evento é disparado. No MXML acima se a
propriedade "myProp " não fosse Bindable este código não seria gerado.
Mas isso é só uma parte do funcionamento do Bindable. Ainda é preciso
definir o que irá acontecer toda vez que o "myProp" mudar.
Primeiramente apenas definimos a propriedade como Bindable. Agora
vamos usá-la.
Test.mxml
========
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="
http://www.adobe.com/2006/mxml"
width="100%" height="100%">
<mx:Script>
<![CDATA[
[Bindable]
private var myProp:String;
]]>
</mx:Script>
<mx:TextInput id="myTextInput" text="{myProp}"/> <!-- USANDO O
BINDING -->
</mx:Application>
Agora, outro trecho de código gerado pelo Flex, desta vez no arquivo
"Test-generated.as" é o seguinte:
Test-generated.as
===============
private function _Test_bindingsSetup():void
{
...
binding = new mx.binding.Binding(this,
function():String
{
var result:* = (myProp);
var stringResult:String = (result == undefined ?
null : String(result));
return stringResult;
},
function(_sourceFunctionReturnValue:String):void
{
myTextInput.text = _sourceFunctionReturnValue;
},
"myTextInput.text");
...
}
Quem quiser entender o que faz cada linha do trecho de código acima
pode olhar no código fonte da classe mx.binding. Binding. Mas em
resumo, é este trecho de código que pega o valor de "myProp" toda vez
que ele mudar e copia para "myTextInput.text".
Por fim, eu gostaria de sintetizar o que o Daniel e o Erko.
Erko (Tese):
"então a dica é: use [bindable] para o que for realmente necessário "
Daniel (Antítese):
"Use bindable para tudo. Acredito ser muito dificil ele prejudicar a
performance de forma a ser perceptíviel"
Beck (Síntese):
Você pode sim usar o Bindable despreocupadamente do ponto de vista da
performance, mas em alguns casos o Bindable reduz a legibilidade do
seu código, o que dificulta na manutenção. Além disso por usar Event
Listeners, o Bindable cria dependências entre os objetos o que impede
que eles sejam excluídos da memória pelo Garbage Collection.
Será que alguém entedeu alguma coisa? Será que alguém leu tudo
isso? :-)
[]'s
Beck Novaes