Com a vinculação de dados unidirecional, é possível definir um valor em um atributo e definir um listener que reaja a uma mudança nesse atributo:
<CheckBox android:id="@+id/rememberMeCheckBox" android:checked="@{viewmodel.rememberMe}" android:onCheckedChanged="@{viewmodel.rememberMeChanged}" />
A vinculação bidirecional de dados fornece um atalho para esse processo:
<CheckBox android:id="@+id/rememberMeCheckBox" android:checked="@={viewmodel.rememberMe}" />
A notação @={}
, que inclui o sinal "=", recebe mudanças de dados
na propriedade e detecta as atualizações dos usuários ao mesmo tempo.
Para reagir às mudanças nos dados de apoio, você pode transformar a variável
de layout em uma implementação de Observable
, geralmente
BaseObservable
, e usar uma anotação
@Bindable
, conforme mostrado no
snippet de código abaixo:
Kotlin
class LoginViewModel : BaseObservable { // val data = ... @Bindable fun getRememberMe(): Boolean { return data.rememberMe } fun setRememberMe(value: Boolean) { // Avoids infinite loops. if (data.rememberMe != value) { data.rememberMe = value // React to the change. saveData() // Notify observers of a new value. notifyPropertyChanged(BR.remember_me) } } }
Java
public class LoginViewModel extends BaseObservable { // private Model data = ... @Bindable public Boolean getRememberMe() { return data.rememberMe; } public void setRememberMe(Boolean value) { // Avoids infinite loops. if (data.rememberMe != value) { data.rememberMe = value; // React to the change. saveData(); // Notify observers of a new value. notifyPropertyChanged(BR.remember_me); } } }
Como o método getter da propriedade vinculável é chamado de getRememberMe()
, o método setter correspondente da propriedade usa automaticamente o nome setRememberMe()
.
Para mais informações sobre o uso de BaseObservable
e @Bindable
, consulte Trabalhar com
objetos de dados observáveis.
Vinculação bidirecional de dados usando atributos personalizados
A plataforma fornece implementações de vinculação de dados bidirecional para os atributos bidirecionais
e listeners de mudança mais comuns, que podem ser usados
como parte do seu app. Se você quiser usar a vinculação de dados bidirecional com atributos
personalizados, trabalhe com as anotações
@InverseBindingAdapter
e
@InverseBindingMethod
.
Por exemplo, se você quiser ativar a vinculação de dados bidirecional em um atributo "time"
em uma visualização personalizada chamada MyView
, siga estas etapas:
Anote o método que define o valor inicial e é atualizado quando o valor muda usando
@BindingAdapter
:Kotlin
@BindingAdapter("time") @JvmStatic fun setTime(view: MyView, newValue: Time) { // Important to break potential infinite loops. if (view.time != newValue) { view.time = newValue } }
Java
@BindingAdapter("time") public static void setTime(MyView view, Time newValue) { // Important to break potential infinite loops. if (view.time != newValue) { view.time = newValue; } }
Anote o método que lê o valor da visualização usando
@InverseBindingAdapter
:Kotlin
@InverseBindingAdapter("time") @JvmStatic fun getTime(view: MyView) : Time { return view.getTime() }
Java
@InverseBindingAdapter("time") public static Time getTime(MyView view) { return view.getTime(); }
Neste ponto, a vinculação de dados sabe o que fazer quando os dados mudam (chama o
método anotado com
@BindingAdapter
) e o que
chamar quando o atributo de visualização muda (chama
InverseBindingListener
).
No entanto, ela não sabe quando ou como o atributo muda.
Para isso, é necessário definir um listener na visualização. Pode ser um listener personalizado
associado à visualização personalizada ou um evento genérico, como perda
de foco ou mudança de texto. Adicione a anotação @BindingAdapter
ao método
que define o listener de mudanças na propriedade:
Kotlin
@BindingAdapter("app:timeAttrChanged") @JvmStatic fun setListeners( view: MyView, attrChange: InverseBindingListener ) { // Set a listener for click, focus, touch, etc. }
Java
@BindingAdapter("app:timeAttrChanged") public static void setListeners( MyView view, final InverseBindingListener attrChange) { // Set a listener for click, focus, touch, etc. }
O listener inclui um InverseBindingListener
como parâmetro. O
InverseBindingListener
é usado para informar ao sistema de vinculação de dados que o atributo
mudou. Então, o sistema pode começar a chamar o método anotado usando
@InverseBindingAdapter
e assim por diante.
Na prática, esse listener inclui uma lógica não trivial, como listeners
para vinculação unidirecional de dados. Para conferir um exemplo, consulte o adaptador da mudança de atributo
de texto,
TextViewBindingAdapter
.
Conversões
Se a variável vinculada a um objeto View
precisar ser formatada, traduzida ou alterada de alguma forma antes de ser exibida,
é possível usar um objeto Converter
.
Por exemplo, use um objeto EditText
que mostre uma data:
<EditText
android:id="@+id/birth_date"
android:text="@={Converter.dateToString(viewmodel.birthDate)}"
/>
O atributo viewmodel.birthDate
contém um valor do tipo Long
, então ele precisa
ser formatado usando um conversor.
Como uma expressão bidirecional está sendo usada, também é necessário que haja um conversor
inverso para permitir que a biblioteca saiba como converter a string fornecida pelo usuário de volta
para o tipo de dados de apoio, nesse caso, Long
. Esse processo é feito adicionando
a anotação @InverseMethod
a um dos conversores e fazendo com que essa anotação faça referência ao conversor
inverso. Um exemplo dessa configuração é mostrado no snippet de
código a seguir:
Kotlin
object Converter { @InverseMethod("stringToDate") @JvmStatic fun dateToString( view: EditText, oldValue: Long, value: Long ): String { // Converts long to String. } @JvmStatic fun stringToDate( view: EditText, oldValue: String, value: String ): Long { // Converts String to long. } }
Java
public class Converter { @InverseMethod("stringToDate") public static String dateToString(EditText view, long oldValue, long value) { // Converts long to String. } public static long stringToDate(EditText view, String oldValue, String value) { // Converts String to long. } }
Loops infinitos usando vinculação de dados bidirecional
Tenha cuidado para não iniciar loops infinitos ao usar a vinculação bidirecional de dados. Quando
o usuário muda um atributo, o método anotado usando
@InverseBindingAdapter
é chamado, e o valor é atribuído à propriedade
de apoio. Isso, por sua vez, chamaria o método anotado usando
@BindingAdapter
, o que acionaria outra chamada para o método anotado
usando @InverseBindingAdapter
e assim por diante.
Por esse motivo, é importante quebrar possíveis loops infinitos comparando
valores novos e antigos dos métodos anotados usando @BindingAdapter
.
Atributos bidirecionais
A plataforma oferece suporte integrado para vinculação de dados bidirecional quando você usa os atributos da tabela a seguir. Para ver detalhes sobre como a plataforma oferece esse suporte, consulte as implementações dos adaptadores de vinculação correspondentes:
Classe. | Atributos | Adaptador de vinculação |
---|---|---|
AdapterView
|
android:selectedItemPosition android:selection |
AdapterViewBindingAdapter
|
CalendarView |
android:date |
CalendarViewBindingAdapter
|
CompoundButton |
android:checked
|
CompoundButtonBindingAdapter
|
DatePicker
|
android:year android:month android:day |
DatePickerBindingAdapter
|
NumberPicker |
android:value
|
NumberPickerBindingAdapter
|
RadioButton
|
android:checkedButton |
RadioGroupBindingAdapter
|
RatingBar
|
android:rating
|
RatingBarBindingAdapter
|
SeekBar
|
android:progress |
SeekBarBindingAdapter
|
TabHost
|
android:currentTab |
TabHostBindingAdapter
|
TextView
|
android:text
|
TextViewBindingAdapter
|
TimePicker
|
android:hour android:minute |
TimePickerBindingAdapter
|
Outros recursos
Para saber mais sobre vinculação de dados, consulte os recursos adicionais a seguir.
Exemplos
- Amostras da Android Data Binding Library (link em inglês)
Codelabs
Postagens do blog
- Vinculação de dados: lições aprendidas (link em inglês)
Recomendados para você
- Observação: o texto do link aparece quando o JavaScript está desativado.
- Trabalhar com objetos de dados observáveis
- Layouts e expressões de vinculação
- Vincular visualizações de layout a componentes de arquitetura