Vor einigen Tagen veröffentlichte Google Android Studio 3.6 Canary 11, die Hauptinnovation von View Binding, die bereits im Mai in Google I / O 2019 beschrieben wurde.

Die Ansichtsbindung ist ein Tool, das das Schreiben von Code für die Interaktion mit der Ansicht erleichtert. Wenn Sie die Ansichtsbindung in einem bestimmten Modul aktivieren, werden Bindungsklassen für jede Layoutdatei im Modul generiert. Das generierte Bindungsklassenobjekt enthält Links zu allen Ansichten aus der Markup-Datei, für die android:id
angegeben ist.
So aktivieren Sie
Um die build.gradle
im Modul zu aktivieren, müssen Sie der Datei build.gradle
ein Element build.gradle
:
android { ... viewBinding { enabled = true } }
Sie können auch angeben, dass Sie keine Bindungsklasse für eine bestimmte Markup-Datei generieren müssen. Dazu müssen Sie das tools:viewBindingIgnore="true"
Attribut angeben tools:viewBindingIgnore="true"
in der tools:viewBindingIgnore="true"
in der gewünschten Markup-Datei.
Wie man es benutzt
Jede generierte Bindungsklasse enthält einen Link zur Stammansicht des Markups ( root
) und Links zu allen Ansichten mit einer ID. Der Name der generierten Klasse wird als "Markup-Dateiname" gebildet, übersetzt in Kamelfall + "Bindung".
Beispiel für die Markup-Datei result_profile.xml
:
<LinearLayout ... > <TextView android:id="@+id/name" /> <ImageView android:cropToPadding="true" /> <Button android:id="@+id/button" android:background="@drawable/rounded_button" /> </LinearLayout>
Die ResultProfileBinding
Klasse wird generiert und enthält zwei Felder: TextView name
und Button button
. Für ImageView
nichts generiert, da es keine id
. Auch in der ResultProfileBinding
Klasse ResultProfileBinding
es eine getRoot()
-Methode, die das Root- LinearLayout
.
Um ein Objekt der Klasse ResultProfileBinding
zu erstellen, müssen Sie die statische Methode inflate()
aufrufen. Danach können Sie die Stammansicht als content view
in der Activity
:
private lateinit var binding: ResultProfileBinding @Override fun onCreate(savedInstanceState: Bundle) { super.onCreate(savedInstanceState) binding = ResultProfileBinding.inflate(layoutInflater) setContentView(binding.root) }
Eine spätere binding
kann verwendet werden, um die Ansicht zu erhalten:
binding.name.text = viewModel.name binding.button.setOnClickListener { viewModel.userClicked() }
Unterschiede zu anderen Ansätzen
Die Hauptvorteile der Ansichtsbindung sind Nullsicherheit und Typensicherheit.
Wenn gleichzeitig eine Ansicht in einer Markup-Konfiguration verfügbar ist, jedoch nicht in einer anderen (z. B. layout-land
), wird in der Bindungsklasse ein @Nullable
Feld dafür generiert.
Wenn in verschiedenen Markup-Konfigurationen eine Ansicht mit derselben ID, aber unterschiedlichen Typen vorhanden ist, wird für sie ein Feld mit dem Typ android.view.View
generiert.
(Zumindest in Version 3.6 von Canary 11)
Im Allgemeinen wäre es praktisch, wenn das generierte Feld den bestmöglichen spezifischen Typ hätte. Beispielsweise wird für eine TextView
in einer Konfiguration und eine TextView
in einer anderen Konfiguration ein Feld vom Typ TextView
generiert ( public class Button extends TextView
).
Bei Verwendung der Ansichtsbindung werden alle Inkonsistenzen zwischen dem Markup und dem Code in der Kompilierungsphase erkannt, wodurch unnötige Fehler während des Anwendungsbetriebs vermieden werden.
Verwendung in RecyclerView.ViewHolder
Nichts verhindert die Verwendung der view
beim Erstellen einer view
für einen RecyclerView.ViewHolder
:
class PersonViewHolder(private val itemPersonBinding: ItemPersonBinding) : RecyclerView.ViewHolder(itemPersonBinding.root) { fun bind(person: Person) { itemPersonBinding.name.text = person.name } }
Um jedoch einen solchen ViewHolder
zu erstellen ViewHolder
ein kleines Boilerplate schreiben:
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PersonViewHolder { val layoutInflater = LayoutInflater.from(parent.context) val itemPersonBinding = ItemPersonBinding.inflate(layoutInflater, parent, false) return PersonViewHolder(itemPersonBinding) }
Es wäre bequemer, wenn die layoutInflater
Methode inflate(...)
bei der Arbeit mit RecyclerView.ViewHolder
nicht über den Parameter layoutInflater
, sondern ihn vom übergebenen parent
layoutInflater
empfängt.
Hier ist auch zu erwähnen, dass bei Verwendung der view
die view
nur einmal über findViewById()
durchsucht wird, wenn die inflate()
-Methode inflate()
. Dies bietet einen Vorteil gegenüber kotlin-android-extensions
, bei denen das Zwischenspeichern von view
standardmäßig nur in Activity
und Fragment
funktioniert und RecyclerView.ViewHolder
eine zusätzliche Konfiguration erfordert.
Im Allgemeinen ist die Ansichtsbindung eine sehr praktische Sache, die in vorhandenen Projekten leicht zu verwenden ist. Creator Butter Knife empfiehlt bereits, zu View Binding zu wechseln.
Schade, dass ein solches Instrument vor einigen Jahren nicht aufgetaucht ist.