Generierte Bindungsklassen

Die Datenbindungsbibliothek generiert Bindungsklassen, mit denen Sie auf die Variablen und Ansichten des Layouts zugreifen können. In dieser Dokumentation erfahren Sie, wie Sie generierte Bindungsklassen erstellen und anpassen.

Die generierte Bindungsklasse verknüpft die Layoutvariablen mit den Ansichten innerhalb des Layouts. Sie können den Namen und das Paket der Bindung anpassen. Alle generierten Bindungsklassen werden von der Klasse ViewDataBinding übernommen.

Für jede Layoutdatei wird eine Bindungsklasse generiert. Der Name der Klasse ist standardmäßig der Name der Layoutdatei, die in die Pascal-Groß- und Kleinschreibung konvertiert wird, wobei das Suffix Binding hinzugefügt wird. Lautet der Name der Layoutdatei beispielsweise activity_main.xml, ist die entsprechende generierte Klasse ActivityMainBinding. Diese Klasse enthält alle Bindungen von den Layouteigenschaften zu den Ansichten des Layouts und weiß, wie Werte für die Bindungsausdrücke zugewiesen werden.

Bindungsobjekt erstellen

Das Bindungsobjekt wird unmittelbar nach der Layout-Inflation erstellt, damit die Ansichtshierarchie nicht geändert wird, bevor es an die Ansichten mit Ausdrücken im Layout gebunden wird. Die gängigste Methode zum Binden des Objekts an ein Layout sind statische Methoden für die Bindungsklasse. Sie können die Ansichtshierarchie erweitern und das Objekt an diese binden. Dazu verwenden Sie die Methode inflate() der Bindungsklasse, wie im folgenden Beispiel gezeigt:

Kotlin

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    val binding: MyLayoutBinding = MyLayoutBinding.inflate(layoutInflater)

    setContentView(binding.root)
}

Java

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    MyLayoutBinding binding = MyLayoutBinding.inflate(getLayoutInflater());

    setContentView(binding.root);
}

Es gibt eine alternative Version der Methode inflate(), die zusätzlich zum Objekt LayoutInflater ein ViewGroup-Objekt verwendet, wie im folgenden Beispiel gezeigt:

Kotlin

val binding: MyLayoutBinding = MyLayoutBinding.inflate(getLayoutInflater(), viewGroup, false)

Java

MyLayoutBinding binding = MyLayoutBinding.inflate(getLayoutInflater(), viewGroup, false);

Wenn das Layout mit einem anderen Mechanismus aufgebläht wird, können Sie es wie folgt separat binden:

Kotlin

val binding: MyLayoutBinding = MyLayoutBinding.bind(viewRoot)

Java

MyLayoutBinding binding = MyLayoutBinding.bind(viewRoot);

Manchmal kennen Sie den Bindungstyp nicht im Voraus. In solchen Fällen können Sie die Bindung mit der Klasse DataBindingUtil erstellen, wie im folgenden Code-Snippet gezeigt:

Kotlin

val viewRoot = LayoutInflater.from(this).inflate(layoutId, parent, attachToParent)
val binding: ViewDataBinding? = DataBindingUtil.bind(viewRoot)

Java

View viewRoot = LayoutInflater.from(this).inflate(layoutId, parent, attachToParent);
ViewDataBinding binding = DataBindingUtil.bind(viewRoot);

Wenn Sie Datenbindungselemente in einem Fragment-, ListView- oder RecyclerView-Adapter verwenden, sollten Sie die inflate()-Methoden der Bindungsklassen oder die DataBindingUtil-Klasse verwenden, wie im folgenden Codebeispiel gezeigt:

Kotlin

val listItemBinding = ListItemBinding.inflate(layoutInflater, viewGroup, false)
// or
val listItemBinding = DataBindingUtil.inflate(layoutInflater, R.layout.list_item, viewGroup, false)

Java

ListItemBinding binding = ListItemBinding.inflate(layoutInflater, viewGroup, false);
// or
ListItemBinding binding = DataBindingUtil.inflate(layoutInflater, R.layout.list_item, viewGroup, false);

Ansichten mit IDs

Die Datenbindungsbibliothek erstellt für jede Ansicht, die eine ID im Layout hat, in der Bindungsklasse ein unveränderliches Feld. Die Datenbindungsbibliothek erstellt beispielsweise die Felder firstName und lastName vom Typ TextView mit dem folgenden Layout:

<layout xmlns:android="http://schemas.android.com/apk/res/android">
   <data>
       <variable name="user" type="com.example.User"/>
   </data>
   <LinearLayout
       android:orientation="vertical"
       android:layout_width="match_parent"
       android:layout_height="match_parent">
       <TextView android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:text="@{user.firstName}"
   android:id="@+id/firstName"/>
       <TextView android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:text="@{user.lastName}"
  android:id="@+id/lastName"/>
   </LinearLayout>
</layout>

Die Bibliothek extrahiert die Ansichten, einschließlich der IDs, in einem einzigen Durchlauf aus der Ansichtshierarchie. Dieser Mechanismus ist möglicherweise schneller als der Aufruf der Methode findViewById() für jede Ansicht im Layout.

IDs sind nicht so notwendig wie ohne Datenbindung. Es gibt jedoch immer noch Fälle, in denen ein Zugriff auf Ansichten aus Code erforderlich ist.

Variablen

Die Datenbindungsbibliothek generiert Zugriffsmethoden für jede im Layout deklarierte Variable. Das folgende Layout generiert beispielsweise Setter- und Getter-Methoden in der Bindungsklasse für die Variablen user, image und note:

<data>
   <import type="android.graphics.drawable.Drawable"/>
   <variable name="user" type="com.example.User"/>
   <variable name="image" type="Drawable"/>
   <variable name="note" type="String"/>
</data>

ViewStubs

Im Gegensatz zu normalen Ansichten beginnen ViewStub-Objekte als unsichtbare Ansichten. Wenn sie sichtbar oder explizit aufgebläht werden, ersetzen sie sich im Layout durch ein anderes Layout.

Da ViewStub aus der Ansichtshierarchie verschwindet, muss auch die Ansicht im Binding-Objekt ausgeblendet werden, damit sie durch die automatische Speicherbereinigung beansprucht werden kann. Da die Ansichten endgültig sind, ersetzt ein ViewStubProxy-Objekt den ViewStub in der generierten Bindungsklasse. Dadurch erhalten Sie Zugriff auf die ViewStub, sofern vorhanden, und auf die aufgeblähte Ansichtshierarchie, wenn ViewStub aufgebläht ist.

Wird ein anderes Layout künstlich erzeugt, muss eine Bindung für das neue Layout festgelegt werden. Daher muss der ViewStubProxy auf ViewStub OnInflateListener warten und bei Bedarf die Bindung erstellen. Da immer nur ein Listener vorhanden sein kann, können Sie mit ViewStubProxy ein OnInflateListener festlegen, das nach dem Einrichten der Bindung aufgerufen wird.

Sofortige Bindung

Wenn sich eine Variable oder ein beobachtbares Objekt ändert, wird die Bindung vor dem nächsten Frame geplant. Manchmal muss die Bindung jedoch sofort ausgeführt werden. Verwenden Sie die Methode executePendingBindings(), um die Ausführung zu erzwingen.

Dynamische Variablen

Manchmal ist die spezifische Bindungsklasse unbekannt. Beispielsweise kennt ein RecyclerView.Adapter, das für beliebige Layouts ausgeführt wird, die spezifische Bindungsklasse nicht. Der Bindungswert muss während des Aufrufs der Methode onBindViewHolder() zugewiesen werden.

Im folgenden Beispiel haben alle Layouts, an die RecyclerView gebunden wird, eine item-Variable. Das BindingHolder-Objekt hat eine getBinding()-Methode, die die ViewDataBinding-Basisklasse zurückgibt.

Kotlin

override fun onBindViewHolder(holder: BindingHolder, position: Int) {
    item: T = items.get(position)
    holder.binding.setVariable(BR.item, item);
    holder.binding.executePendingBindings();
}

Java

public void onBindViewHolder(BindingHolder holder, int position) {
    final T item = items.get(position);
    holder.getBinding().setVariable(BR.item, item);
    holder.getBinding().executePendingBindings();
}

Hintergrundthread

Sie können Ihr Datenmodell in einem Hintergrundthread ändern, solange es sich nicht um eine Sammlung handelt. Die Datenbindung lokalisiert jede Variable oder jedes Feld während der Bewertung, um Probleme mit der Gleichzeitigkeit zu vermeiden.

Namen von benutzerdefinierten Bindungsklassen

Standardmäßig wird eine Bindungsklasse anhand des Namens der Layoutdatei generiert. Sie beginnt mit einem Großbuchstaben, entfernt die Unterstriche ( _), die Großschreibung des folgenden Buchstabens und das Wort Binding wird als Suffix hinzugefügt. Die Layoutdatei contact_item.xml generiert beispielsweise die Klasse ContactItemBinding. Die Klasse wird in einem databinding-Paket unter dem Modulpaket platziert. Wenn das Modulpaket beispielsweise com.example.my.app ist, wird die Bindungsklasse im Paket com.example.my.app.databinding platziert.

Bindungsklassen können durch Anpassung des Attributs class des Elements data umbenannt oder in verschiedenen Paketen platziert werden. Das folgende Layout generiert beispielsweise die Bindungsklasse ContactItem im Paket databinding im aktuellen Modul:

<data class="ContactItem">
    ...
</data>

Sie können die Bindungsklasse in einem anderen Paket generieren, indem Sie dem Klassennamen einen Punkt voranstellen. Im folgenden Beispiel wird die Bindungsklasse im Modulpaket generiert:

<data class=".ContactItem">
    ...
</data>

Sie können auch den vollständigen Paketnamen verwenden, für den die Bindungsklasse generiert werden soll. Im folgenden Beispiel wird die Bindungsklasse ContactItem im Paket com.example erstellt:

<data class="com.example.ContactItem">
    ...
</data>

Weitere Informationen

Weitere Informationen zur Datenbindung finden Sie in den folgenden zusätzlichen Ressourcen.