Die lang erwartete View Binding in Android

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.

Source: https://habr.com/ru/post/de467295/


All Articles