Observabilidade é a capacidade de um objeto de notificar outros sobre mudanças nos dados deles. A Data Binding Library permite que você faça com que objetos, campos ou coleções sejam observáveis.
Qualquer objeto antigo pode ser usado para vinculação de dados, mas a modificação do objeto não faz com que a IU seja atualizada automaticamente. A vinculação de dados pode ser usada para possibilitar que seus objetos de dados notifiquem outros objetos, conhecidos como listeners, quando os dados deles mudarem. Existem três tipos de classes observáveis: objetos, campos e coleções.
Quando um desses objetos de dados observáveis é vinculado à IU e uma propriedade do objeto de dados muda, a IU é atualizada automaticamente.
Campos observáveis
Criar classes que implementem a interface Observable
envolve certo trabalho, que pode não valer a pena caso suas classes tenham apenas algumas propriedades. Nesse caso, você pode usar a classe genérica Observable
e as classes específicas de primitivos a seguir para tornar os campos observáveis:
ObservableBoolean
ObservableByte
ObservableChar
ObservableShort
ObservableInt
ObservableLong
ObservableFloat
ObservableDouble
ObservableParcelable
Os campos observáveis são objetos observáveis independentes que têm um único campo. As versões primitivas evitam a conversão boxing e unboxing durante operações de acesso. Para usar esse mecanismo, crie uma propriedade public final
na linguagem de programação Java ou uma propriedade somente de leitura em Kotlin, conforme mostrado no exemplo a seguir:
Kotlin
class User { val firstName = ObservableField<String>() val lastName = ObservableField<String>() val age = ObservableInt() }
Java
private static class User { public final ObservableField<String> firstName = new ObservableField<>(); public final ObservableField<String> lastName = new ObservableField<>(); public final ObservableInt age = new ObservableInt(); }
Para acessar o valor do campo, use os métodos do acessador set()
e get()
ou use a sintaxe de propriedade do Kotlin (link em inglês):
Kotlin
user.firstName = "Google" val age = user.age
Java
user.firstName.set("Google"); int age = user.age.get();
Coleções observáveis
Alguns apps usam estruturas dinâmicas para reter dados. As coleções observáveis permitem acessar essas estruturas usando uma chave. A classe ObservableArrayMap
é útil quando a chave é um tipo de referência, como String
, conforme mostrado no exemplo a seguir:
Kotlin
ObservableArrayMap<String, Any>().apply { put("firstName", "Google") put("lastName", "Inc.") put("age", 17) }
Java
ObservableArrayMap<String, Object> user = new ObservableArrayMap<>(); user.put("firstName", "Google"); user.put("lastName", "Inc."); user.put("age", 17);
No layout, o mapa pode ser encontrado usando as chaves da string, da seguinte maneira:
<data>
<import type="android.databinding.ObservableMap"/>
<variable name="user" type="ObservableMap<String, Object>"/>
</data>
…
<TextView
android:text="@{user.lastName}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:text="@{String.valueOf(1 + (Integer)user.age)}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
A classe ObservableArrayList
é útil quando a chave é um número inteiro, conforme mostrado a seguir:
Kotlin
ObservableArrayList<Any>().apply { add("Google") add("Inc.") add(17) }
Java
ObservableArrayList<Object> user = new ObservableArrayList<>(); user.add("Google"); user.add("Inc."); user.add(17);
No layout, a lista pode ser acessada por meio dos índices, conforme mostrado no exemplo a seguir:
<data>
<import type="android.databinding.ObservableList"/>
<import type="com.example.my.app.Fields"/>
<variable name="user" type="ObservableList<Object>"/>
</data>
…
<TextView
android:text='@{user[Fields.LAST_NAME]}'
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:text='@{String.valueOf(1 + (Integer)user[Fields.AGE])}'
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
Objetos observáveis
Uma classe que implementa a interface Observable
permite registrar listeners que queiram ser notificados sobre mudanças em propriedades do objeto observável.
A interface Observable
tem um mecanismo para adicionar e remover listeners, mas é preciso decidir quando as notificações serão enviadas. Para facilitar o desenvolvimento, a Data Binding Library oferece a classe BaseObservable
, que implementa o mecanismo de registro de listener. A classe de dados que implementa BaseObservable
é responsável por notificar quando as propriedades mudam. Para isso, atribua uma anotação Bindable
ao getter e chame o método notifyPropertyChanged()
no setter, conforme mostrado no exemplo a seguir:
Kotlin
class User : BaseObservable() { @get:Bindable var firstName: String = "" set(value) { field = value notifyPropertyChanged(BR.firstName) } @get:Bindable var lastName: String = "" set(value) { field = value notifyPropertyChanged(BR.lastName) } }
Java
private static class User extends BaseObservable { private String firstName; private String lastName; @Bindable public String getFirstName() { return this.firstName; } @Bindable public String getLastName() { return this.lastName; } public void setFirstName(String firstName) { this.firstName = firstName; notifyPropertyChanged(BR.firstName); } public void setLastName(String lastName) { this.lastName = lastName; notifyPropertyChanged(BR.lastName); } }
A vinculação de dados gera uma classe chamada BR
no pacote do módulo, que contém os códigos dos recursos usados para a vinculação de dados. A anotação Bindable
gera uma entrada no arquivo da classe BR
durante a compilação. Caso não seja possível mudar a classe base das classes de dados, a interface Observable
pode ser implementada usando um objeto PropertyChangeRegistry
para registrar e notificar os listeners de forma eficiente.
Outros recursos
Para saber mais sobre vinculação de dados, consulte os seguintes recursos adicionais.