Mit der unidirektionalen Datenbindung können Sie einen Wert für ein Attribut festlegen und einen Listener festlegen, der auf eine Änderung dieses Attributs reagiert:
<CheckBox android:id="@+id/rememberMeCheckBox" android:checked="@{viewmodel.rememberMe}" android:onCheckedChanged="@{viewmodel.rememberMeChanged}" />
Mit der bidirektionalen Datenbindung lässt sich dieser Vorgang beschleunigen:
<CheckBox android:id="@+id/rememberMeCheckBox" android:checked="@={viewmodel.rememberMe}" />
Die @={}
-Notation, die vor allem das Zeichen „=“ enthält, empfängt Datenänderungen an der Property und wartet gleichzeitig auf Nutzeraktualisierungen.
Wenn Sie auf Änderungen in den zugrunde liegenden Daten reagieren möchten, können Sie Ihre Layoutvariable als Implementierung von Observable
festlegen (in der Regel BaseObservable
) und eine @Bindable
-Annotation verwenden, wie im folgenden Code-Snippet gezeigt:
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); } } }
Da die Getter-Methode des bindbaren Attributs getRememberMe()
heißt, verwendet die entsprechende Setter-Methode des Attributs automatisch den Namen setRememberMe()
.
Weitere Informationen zur Verwendung von BaseObservable
und @Bindable
finden Sie unter Mit beobachtbaren Datenobjekten arbeiten.
Bidirektionale Datenbindung mithilfe benutzerdefinierter Attribute
Die Plattform bietet bidirektionale Implementierungen der Datenbindung für die gängigsten bidirektionalen Attribute und Änderungs-Listener, die Sie im Rahmen Ihrer Anwendung verwenden können. Wenn Sie die bidirektionale Datenbindung mit benutzerdefinierten Attributen nutzen möchten, müssen Sie mit den Annotationen @InverseBindingAdapter
und @InverseBindingMethod
arbeiten.
Wenn Sie beispielsweise die bidirektionale Datenbindung für ein "time"
-Attribut in einer benutzerdefinierten Ansicht namens MyView
aktivieren möchten, führen Sie die folgenden Schritte aus:
Annotieren Sie die Methode, die den Anfangswert festlegt und aktualisiert, wenn sich der Wert ändert, indem Sie
@BindingAdapter
verwenden: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; } }
Annotieren Sie die Methode, die den Wert aus der Ansicht liest, mithilfe von
@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(); }
An dieser Stelle weiß die Datenbindung, was zu tun ist, wenn sich die Daten ändern (die mit @BindingAdapter
annotierte Methode wird aufgerufen) und was aufgerufen werden soll, wenn sich das Ansichtsattribut ändert (InverseBindingListener
). Sie weiß jedoch nicht, wann oder wie sich das Attribut ändert.
Dazu müssen Sie für die Ansicht einen Listener festlegen. Dabei kann es sich um einen benutzerdefinierten Listener handeln, der mit Ihrer benutzerdefinierten Ansicht verknüpft ist, oder um ein allgemeines Ereignis wie Fokusverlust oder Textänderung. Fügen Sie der Methode, die den Listener für Änderungen an der Eigenschaft festlegt, die Anmerkung @BindingAdapter
hinzu:
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. }
Der Listener enthält einen InverseBindingListener
als Parameter. Mit InverseBindingListener
teilen Sie dem Datenbindungssystem mit, dass sich das Attribut geändert hat. Das System kann dann die mit @InverseBindingAdapter
annotierte Methode aufrufen usw.
In der Praxis enthält dieser Listener einige nicht triviale Logik, einschließlich Listener für unidirektionale Datenbindungen. Ein Beispiel finden Sie im Adapter für die Textattributänderung TextViewBindingAdapter
.
Nutzer mit Conversion
Wenn die an ein View
-Objekt gebundene Variable vor der Anzeige formatiert, übersetzt oder geändert werden muss, kann ein Converter
-Objekt verwendet werden.
Nehmen wir z. B. ein EditText
-Objekt, das ein Datum anzeigt:
<EditText
android:id="@+id/birth_date"
android:text="@={Converter.dateToString(viewmodel.birthDate)}"
/>
Das Attribut viewmodel.birthDate
enthält einen Wert vom Typ Long
. Es muss daher mit einem Converter formatiert werden.
Da ein bidirektionaler Ausdruck verwendet wird, muss auch ein Inverse Converter vorhanden sein, damit die Bibliothek weiß, wie der vom Nutzer bereitgestellte String zurück in den unterstützenden Datentyp konvertiert wird, in diesem Fall Long
. Dazu wird einem der Konverter die Annotation @InverseMethod
hinzugefügt und diese Annotation auf den Inverse-Converter verweisen. Ein Beispiel für diese Konfiguration wird im folgenden Code-Snippet angezeigt:
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. } }
Endlosschleifen mit bidirektionaler Datenbindung
Achten Sie bei der Verwendung der bidirektionalen Datenbindung darauf, keine Endlosschleifen einzuführen. Wenn der Nutzer ein Attribut ändert, wird die mit @InverseBindingAdapter
annotierte Methode aufgerufen und der Wert der unterstützenden Property zugewiesen. Dies wiederum würde die mit @BindingAdapter
annotierte Methode aufrufen, die einen weiteren Aufruf der mit @InverseBindingAdapter
annotierten Methode auslösen usw.
Aus diesem Grund ist es wichtig, mögliche Endlosschleifen zu durchbrechen, indem neue und alte Werte in den mit @BindingAdapter
annotierten Methoden verglichen werden.
Zweiwege-Attribute
Die Plattform bietet integrierte Unterstützung für die bidirektionale Datenbindung, wenn Sie die Attribute in der folgenden Tabelle verwenden. Weitere Informationen dazu, wie die Plattform diese Unterstützung bietet, finden Sie in den Implementierungen für die entsprechenden Bindungsadapter:
Klasse | Attribut(e) | Bindungsadapter |
---|---|---|
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
|
Weitere Informationen
Weitere Informationen zur Datenbindung finden Sie in den folgenden zusätzlichen Ressourcen.
Produktproben
Codelabs
Blogposts
Empfehlungen für dich
- Hinweis: Der Linktext wird angezeigt, wenn JavaScript deaktiviert ist.
- Mit beobachtbaren Datenobjekten arbeiten
- Layouts und Bindungsausdrücke
- Layoutansichten an Architekturkomponenten binden