Con la vinculación de datos unidireccional, puedes establecer un valor en un atributo y configurar un objeto de escucha que reaccione a un cambio en ese atributo:
<CheckBox android:id="@+id/rememberMeCheckBox" android:checked="@{viewmodel.rememberMe}" android:onCheckedChanged="@{viewmodel.rememberMeChanged}" />
La vinculación de datos bidireccional proporciona un acceso directo a este proceso:
<CheckBox android:id="@+id/rememberMeCheckBox" android:checked="@={viewmodel.rememberMe}" />
La notación @={}, que incluye el signo "=", recibe cambios de datos en la propiedad y escucha las actualizaciones del usuario al mismo tiempo.
Para reaccionar a los cambios en los datos de copia de seguridad, puedes hacer que tu variable de diseño sea una implementación de Observable, por lo general, BaseObservable, y usar una anotación @Bindable, como se muestra en el siguiente fragmento de código:
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);
}
}
}
Debido a que se llama al método get de la propiedad vinculable getRememberMe(), el método set correspondiente de la propiedad usa automáticamente el nombre setRememberMe().
Para obtener más información sobre el uso de BaseObservable y @Bindable, consulta Cómo trabajar con objetos de datos observables.
Vinculación de datos bidireccional con atributos personalizados
La plataforma proporciona implementaciones de vinculación de datos bidireccional para los atributos bidireccionales más comunes y los objetos de escucha de cambios, que puedes usar como parte de tu app. Si deseas usar la vinculación de datos bidireccional con atributos personalizados, debes trabajar con las anotaciones @InverseBindingAdapter y @InverseBindingMethod.
Por ejemplo, si quieres habilitar la vinculación de datos bidireccional en un atributo "time" en una vista personalizada llamada MyView, completa los siguientes pasos:
Anota el método que establece el valor inicial y se actualiza cuando cambia el valor con
@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; } }Anota el método que lee el valor de la vista con
@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(); }
En este punto, la vinculación de datos sabe qué hacer cuando cambian los datos (llama al método anotado con @BindingAdapter) y qué llamar cuando cambia el atributo de vista (llama a InverseBindingListener). Sin embargo, no sabe cuándo ni cómo cambia el atributo.
Para eso, necesitas establecer un objeto de escucha en la vista. Puede ser un objeto de escucha personalizado asociado con tu vista personalizada o un evento genérico, como una pérdida de enfoque o un cambio de texto. Agrega la anotación @BindingAdapter al método que establece el objeto de escucha para los cambios en la propiedad:
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.
}
El objeto de escucha incluye un InverseBindingListener como parámetro. Usa InverseBindingListener para indicarle al sistema de vinculación de datos que el atributo cambió. Luego, el sistema puede comenzar a llamar al método anotado con @InverseBindingAdapter.
En la práctica, este objeto de escucha incluye cierta lógica no trivial, incluidos los objetos de escucha para la vinculación de datos unidireccional. Para ver un ejemplo, consulta el adaptador para el cambio de atributo de texto, TextViewBindingAdapter.
Convertidores
Si la variable vinculada a un objeto View debe tener un formato, traducirse o cambiarse de alguna manera antes de mostrarse, es posible usar un objeto Converter.
Por ejemplo, toma un objeto EditText que muestra una fecha:
<EditText
android:id="@+id/birth_date"
android:text="@={Converter.dateToString(viewmodel.birthDate)}"
/>
El atributo viewmodel.birthDate contiene un valor de tipo Long, por lo que se debe formatear con un convertidor.
Como se usa una expresión bidireccional, también debe haber un conversor inverso para que la biblioteca sepa cómo volver a convertir la cadena proporcionada por el usuario en el tipo de datos de copia de seguridad, en este caso, Long. Para ello, agrega la anotación @InverseMethod a uno de los convertidores y haz que esta anotación haga referencia al convertidor inverso. En el siguiente fragmento de código, se muestra un ejemplo de esta configuración:
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.
}
}
Bucles infinitos con vinculación de datos bidireccional
Ten cuidado de no introducir bucles infinitos cuando uses la vinculación de datos bidireccional. Cuando el usuario cambia un atributo, se llama al método anotado con @InverseBindingAdapter y se asigna el valor a la propiedad de copia de seguridad. Esto, a su vez, llamaría al método anotado con @BindingAdapter, lo que activaría otra llamada al método anotado con @InverseBindingAdapter, lo que continuaría el bucle.
Por este motivo, es importante romper los posibles bucles infinitos comparando los valores nuevos y antiguos en los métodos anotados con @BindingAdapter.
Atributos bidireccionales
La plataforma proporciona compatibilidad integrada para la vinculación de datos bidireccional cuando usas los atributos de la siguiente tabla. Para obtener detalles sobre cómo la plataforma proporciona esta compatibilidad, consulta las implementaciones de los adaptadores de vinculación correspondientes:
| Clase | Atributo(s) | Adaptador de vinculación |
|---|---|---|
AdapterView
|
android:selectedItemPositionandroid:selection |
AdapterViewBindingAdapter
|
CalendarView |
android:date |
CalendarViewBindingAdapter
|
CompoundButton |
android:checked
|
CompoundButtonBindingAdapter
|
DatePicker
|
android:yearandroid:monthandroid: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:hourandroid:minute |
TimePickerBindingAdapter
|
Recursos adicionales
Para obtener más información sobre la vinculación de datos, consulta los siguientes recursos adicionales.
Ejemplos
Codelabs
Entradas de blog
Recomendaciones para ti
- Nota: El texto del vínculo se muestra cuando JavaScript está desactivado
- Cómo trabajar con objetos de datos observables
- Diseños y expresiones vinculantes
- Cómo vincular vistas de diseño con componentes de arquitectura