Ansichtsbindung   Teil von Android Jetpack.

Die Aufrufbindung ist eine Funktion, mit der sich Code einfacher schreiben lässt, der mit Ansichten interagiert. Sobald die Ansichtsbindung in einem Modul aktiviert ist, wird für jede XML-Layoutdatei in diesem Modul eine Bindungsklasse generiert. Eine Instanz einer Bindungsklasse enthält direkte Verweise auf alle Ansichten, die im entsprechenden Layout eine ID haben.

In den meisten Fällen wird findViewById durch die Bindung an die Ansicht ersetzt.

Einrichten

Die Bindung von Ansichten wird pro Modul aktiviert. Wenn Sie die Ansichtsbindung in einem Modul aktivieren möchten, setzen Sie die Build-Option viewBinding in der Datei build.gradle auf Modulebene auf true, wie im folgenden Beispiel gezeigt:

Groovy

android {
    ...
    buildFeatures {
        viewBinding true
    }
}

Kotlin

android {
    ...
    buildFeatures {
        viewBinding = true
    }
}

Wenn eine Layoutdatei beim Generieren von Bindungsklassen ignoriert werden soll, fügen Sie der Stammansicht dieser Layoutdatei das Attribut tools:viewBindingIgnore="true" hinzu:

<LinearLayout
        ...
        tools:viewBindingIgnore="true" >
    ...
</LinearLayout>

Nutzung

Wenn die Ansichtsbindung für ein Modul aktiviert ist, wird für jede XML-Layoutdatei, die das Modul enthält, eine Bindungsklasse generiert. Jede Bindungsklasse enthält Verweise auf die Stammansicht und alle Ansichten mit einer ID. Der Name der Bindungsklasse wird generiert, indem der Name der XML-Datei in Pascal-Schrift umgewandelt und am Ende das Wort „Binding“ hinzugefügt wird.

Angenommen, Sie haben eine Layoutdatei namens result_profile.xml mit folgendem Inhalt:

<LinearLayout ... >
    <TextView android:id="@+id/name" />
    <ImageView android:cropToPadding="true" />
    <Button android:id="@+id/button"
        android:background="@drawable/rounded_button" />
</LinearLayout>

Die generierte Bindungsklasse heißt ResultProfileBinding. Diese Klasse hat zwei Felder: eine TextView namens name und eine Button namens button. Das Element ImageView im Layout hat keine ID, sodass in der Bindungsklasse keine Referenz darauf vorhanden ist.

Jede Bindungsklasse enthält außerdem eine getRoot()-Methode, die eine direkte Referenz auf die Stammansicht der entsprechenden Layoutdatei enthält. In diesem Beispiel gibt die Methode getRoot() in der Klasse ResultProfileBinding die Stammansicht LinearLayout zurück.

In den folgenden Abschnitten wird die Verwendung generierter Bindungsklassen in Aktivitäten und Fragmenten veranschaulicht.

Ansichtsbindung in Aktivitäten verwenden

Wenn Sie eine Instanz der Bindungsklasse für die Verwendung mit einer Aktivität einrichten möchten, führen Sie in der onCreate()-Methode der Aktivität die folgenden Schritte aus:

  1. Rufen Sie die statische Methode inflate() in der generierten Bindungsklasse auf. Dadurch wird eine Instanz der Bindungsklasse für die Aktivität erstellt.
  2. Rufen Sie die Methode getRoot() auf oder verwenden Sie die Kotlin-Attributsyntax, um eine Referenz auf die Stammansicht abzurufen.
  3. Übergeben Sie die Stammansicht an setContentView(), um sie zur aktiven Ansicht auf dem Bildschirm zu machen.

Diese Schritte sind im folgenden Beispiel dargestellt:

Kotlin

private lateinit var binding: ResultProfileBinding

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    binding = ResultProfileBinding.inflate(layoutInflater)
    val view = binding.root
    setContentView(view)
}

Java

private ResultProfileBinding binding;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    binding = ResultProfileBinding.inflate(getLayoutInflater());
    View view = binding.getRoot();
    setContentView(view);
}

Sie können jetzt die Instanz der Bindungsklasse verwenden, um auf eine der Ansichten zu verweisen:

Kotlin

binding.name.text = viewModel.name
binding.button.setOnClickListener { viewModel.userClicked() }

Java

binding.name.setText(viewModel.getName());
binding.button.setOnClickListener(new View.OnClickListener() {
    viewModel.userClicked()
});

Bindung von Ansichten in Fragmenten verwenden

Wenn Sie eine Instanz der Bindungsklasse für die Verwendung mit einem Fragment einrichten möchten, führen Sie die folgenden Schritte in der Methode onCreateView() des Fragments aus:

  1. Rufen Sie die statische Methode inflate() in der generierten Bindungsklasse auf. Dadurch wird eine Instanz der Bindungsklasse für das zu verwendende Fragment erstellt.
  2. Rufen Sie die Methode getRoot() auf oder verwenden Sie die Kotlin-Attributsyntax, um eine Referenz auf die Stammansicht abzurufen.
  3. Gib die Stammansicht aus der onCreateView()-Methode zurück, um sie zur aktiven Ansicht auf dem Bildschirm zu machen.

Kotlin

private var _binding: ResultProfileBinding? = null
// This property is only valid between onCreateView and
// onDestroyView.
private val binding get() = _binding!!

override fun onCreateView(
    inflater: LayoutInflater,
    container: ViewGroup?,
    savedInstanceState: Bundle?
): View? {
    _binding = ResultProfileBinding.inflate(inflater, container, false)
    val view = binding.root
    return view
}

override fun onDestroyView() {
    super.onDestroyView()
    _binding = null
}

Java

private ResultProfileBinding binding;

@Override
public View onCreateView (LayoutInflater inflater,
                          ViewGroup container,
                          Bundle savedInstanceState) {
    binding = ResultProfileBinding.inflate(inflater, container, false);
    View view = binding.getRoot();
    return view;
}

@Override
public void onDestroyView() {
    super.onDestroyView();
    binding = null;
}

Sie können jetzt die Instanz der Bindungsklasse verwenden, um auf eine der Ansichten zu verweisen:

Kotlin

binding.name.text = viewModel.name
binding.button.setOnClickListener { viewModel.userClicked() }

Java

binding.name.setText(viewModel.getName());
binding.button.setOnClickListener(new View.OnClickListener() {
    viewModel.userClicked()
});

Hinweise für verschiedene Konfigurationen angeben

Wenn Sie Ansichten in mehreren Konfigurationen deklarieren, kann es je nach Layout sinnvoll sein, einen anderen Ansichtstyp zu verwenden. Das folgende Code-Snippet zeigt ein Beispiel dafür:

# in res/layout/example.xml

<TextView android:id="@+id/user_bio" />

# in res/layout-land/example.xml

<EditText android:id="@+id/user_bio" />

In diesem Fall würden Sie erwarten, dass die generierte Klasse ein Feld userBio vom Typ TextView enthält, da TextView die gemeinsame Basisklasse ist. Aufgrund technischer Einschränkungen kann der Codegenerator für die Bindung an die Ansicht dies nicht ermitteln und generiert stattdessen ein View-Feld. Dazu muss das Feld später mit binding.userBio as TextView gecastet werden.

Um diese Einschränkung zu umgehen, unterstützt die Ansichtsbindung ein tools:viewBindingType-Attribut, mit dem Sie dem Compiler mitteilen können, welcher Typ im generierten Code verwendet werden soll. Im vorherigen Beispiel können Sie dieses Attribut verwenden, um den Compiler dazu zu bringen, das Feld als TextView zu generieren:

# in res/layout/example.xml (unchanged)

<TextView android:id="@+id/user_bio" />

# in res/layout-land/example.xml

<EditText android:id="@+id/user_bio" tools:viewBindingType="TextView" />

Angenommen, Sie haben zwei Layouts, eines mit einem BottomNavigationView und eines mit einem NavigationRailView. Beide Klassen erweitern NavigationBarView, das die meisten Implementierungsdetails enthält. Wenn in Ihrem Code nicht genau bekannt sein muss, welche Unterklasse im aktuellen Layout vorhanden ist, können Sie mit tools:viewBindingType den generierten Typ in beiden Layouts auf NavigationBarView festlegen:

# in res/layout/navigation_example.xml

<BottomNavigationView android:id="@+id/navigation" tools:viewBindingType="NavigationBarView" />

# in res/layout-w720/navigation_example.xml

<NavigationRailView android:id="@+id/navigation" tools:viewBindingType="NavigationBarView" />

Bei der View-Bindung kann der Wert dieses Attributs beim Generieren von Code nicht überprüft werden. Um Kompilierungs- und Laufzeitfehler zu vermeiden, muss der Wert die folgenden Bedingungen erfüllen:

  • Der Wert muss eine Klasse sein, die von android.view.View erbt.
  • Der Wert muss eine Superklasse des Tags sein, auf dem er platziert ist. Die folgenden Werte funktionieren beispielsweise nicht:

      <TextView tools:viewBindingType="ImageView" /> <!-- ImageView is not related to TextView. -->
      <TextView tools:viewBindingType="Button" /> <!-- Button is not a superclass of TextView. -->
    
  • Der endgültige Typ muss für alle Konfigurationen einheitlich aufgelöst werden.

Unterschiede zu findViewById

Die View-Bindung bietet gegenüber der Verwendung von findViewById wichtige Vorteile:

  • Null-Sicherheit:Da durch die View-Bindung direkte Verweise auf Views erstellt werden, besteht keine Gefahr einer Nullzeigerausnahme aufgrund einer ungültigen View-ID. Wenn eine Ansicht nur in einigen Konfigurationen eines Layouts vorhanden ist, wird das Feld mit der Referenz in der Bindungsklasse mit @Nullable gekennzeichnet.
  • Typsicherheit:Die Felder in jeder Bindungsklasse haben Typen, die den Ansichten entsprechen, auf die sie in der XML-Datei verweisen. Das bedeutet, dass keine Klasse zu einer Ausnahme führt.

Diese Unterschiede führen dazu, dass Inkompatibilitäten zwischen Ihrem Layout und Ihrem Code dazu führen, dass Ihr Build nicht zur Laufzeit, sondern zur Kompilierungszeit fehlschlägt.

Vergleich mit Datenbindung

Sowohl bei der Ansichtsbindung als auch bei der Datenbindung werden Bindungsklassen generiert, mit denen Sie direkt auf Ansichten verweisen können. Die Ansichtsbindung ist jedoch für einfachere Anwendungsfälle gedacht und bietet gegenüber der Datenbindung folgende Vorteile:

  • Schnellere Kompilierung:Die Ansichtsbindung erfordert keine Anmerkungsverarbeitung, sodass die Kompilierungszeiten kürzer sind.
  • Einfache Bedienung:Für die View-Bindung sind keine speziell getaggten XML-Layoutdateien erforderlich. Sie lässt sich daher schneller in Ihren Apps implementieren. Wenn Sie die Ansichtsbindung in einem Modul aktivieren, wird sie automatisch auf alle Layouts dieses Moduls angewendet.

Die Ansichtsbindung hat im Vergleich zur Datenbindung jedoch die folgenden Einschränkungen:

Aus diesen Gründen ist es in einigen Fällen am besten, in einem Projekt sowohl die Bindung an die Ansicht als auch die Datenbindung zu verwenden. Sie können die Datenbindung in Layouts verwenden, für die erweiterte Funktionen erforderlich sind, und die Ansichtsbindung in Layouts, für die dies nicht der Fall ist.

Weitere Informationen

Weitere Informationen zur View-Bindung finden Sie in den folgenden Ressourcen:

Blogs

Videos