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:
- Rufen Sie die statische Methode
inflate()
in der generierten Bindungsklasse auf. Dadurch wird eine Instanz der Bindungsklasse für die Aktivität erstellt. - Rufen Sie die Methode
getRoot()
auf oder verwenden Sie die Kotlin-Attributsyntax, um eine Referenz auf die Stammansicht abzurufen. - Ü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:
- Rufen Sie die statische Methode
inflate()
in der generierten Bindungsklasse auf. Dadurch wird eine Instanz der Bindungsklasse für das zu verwendende Fragment erstellt. - Rufen Sie die Methode
getRoot()
auf oder verwenden Sie die Kotlin-Attributsyntax, um eine Referenz auf die Stammansicht abzurufen. - 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:
- Die Ansichtsbindung unterstützt keine Layoutvariablen oder Layoutausdrücke. Daher können damit keine dynamischen UI-Inhalte direkt aus XML-Layoutdateien deklariert werden.
- Die Ansichtsbindung unterstützt keine zwei-Wege-Datenbindung.
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
Empfehlungen für dich
- Hinweis: Der Linktext wird angezeigt, wenn JavaScript deaktiviert ist.
- Von Kotlin-Synthesen zu Jetpack-Ansichtsbindung migrieren
- Layouts und Bindungsausdrücke
- App-Architektur: UI-Ebene – Einführung – Android-Entwickler