Il y a quelques jours, Google a sorti Android Studio 3.6 Canary 11, la principale innovation dans laquelle était View Binding, qui a été décrite en mai sur Google I / O 2019.

La liaison de vue est un outil qui facilite l'écriture de code pour interagir avec la vue. Lorsque vous activez la liaison de vues dans un module spécifique, il génÚre des classes de liaison pour chaque fichier de disposition du module. L'objet de classe de liaison généré contient des liens vers toutes les vues du fichier de balisage pour lesquelles android:id
est spécifié.
Comment activer
Pour activer View Binding dans le module, vous devez ajouter un élément au fichier build.gradle
:
android { ... viewBinding { enabled = true } }
Vous pouvez également spécifier que vous n'avez pas besoin de générer une classe de liaison pour un fichier de balisage particulier. Pour ce faire, vous devez spécifier l'attribut tools:viewBindingIgnore="true"
dans la vue racine du fichier de balisage souhaité.
Comment utiliser
Chaque classe de liaison générée contient un lien vers la vue racine du balisage ( root
) et des liens vers toutes les vues qui ont un identifiant. Le nom de la classe générée est formé comme "nom de fichier de balisage" traduit en camel case + "Binding".
Par exemple, pour le fichier de balisage result_profile.xml
:
<LinearLayout ... > <TextView android:id="@+id/name" /> <ImageView android:cropToPadding="true" /> <Button android:id="@+id/button" android:background="@drawable/rounded_button" /> </LinearLayout>
La classe ResultProfileBinding
sera générée, contenant 2 champs: TextView name
et Button button
. Pour ImageView
rien ne sera généré, car il n'a pas d' id
. Toujours dans la classe ResultProfileBinding
, ResultProfileBinding
aura une méthode getRoot()
qui renvoie la racine LinearLayout
.
Pour créer un objet de la classe ResultProfileBinding
, vous devez appeler la méthode statique inflate()
. AprĂšs cela, vous pouvez utiliser la vue racine comme vue de content view
dans l' Activity
:
private lateinit var binding: ResultProfileBinding @Override fun onCreate(savedInstanceState: Bundle) { super.onCreate(savedInstanceState) binding = ResultProfileBinding.inflate(layoutInflater) setContentView(binding.root) }
Une binding
ultĂ©rieure peut ĂȘtre utilisĂ©e pour obtenir la vue:
binding.name.text = viewModel.name binding.button.setOnClickListener { viewModel.userClicked() }
Différences par rapport à d'autres approches
Les principaux avantages de View Binding sont la sécurité nulle et la sécurité de type.
Dans le mĂȘme temps, si une vue est disponible dans une configuration de balisage, mais pas dans une autre ( layout-land
, par exemple), un champ @Nullable
sera généré pour elle dans la classe de liaison.
De plus, si dans diffĂ©rentes configurations de balisage il y a une vue avec le mĂȘme id, mais des types diffĂ©rents, un champ avec le type android.view.View
sera généré pour eux.
(Au moins dans la version 3.6 de Canary 11)
En général, il serait pratique que le champ généré ait le type spécifique le plus possible. Par exemple, pour un Button
dans une configuration et un TextView
dans une autre, un champ de type TextView
généré ( public class Button extends TextView
).
Lors de l'utilisation de View Binding, toutes les incohérences entre le balisage et le code seront détectées au stade de la compilation, ce qui évitera des erreurs inutiles pendant le fonctionnement de l'application.
Utilisation dans RecyclerView.ViewHolder
Rien n'empĂȘche d'utiliser la liaison de vues lors de la crĂ©ation d'une view
pour un RecyclerView.ViewHolder
:
class PersonViewHolder(private val itemPersonBinding: ItemPersonBinding) : RecyclerView.ViewHolder(itemPersonBinding.root) { fun bind(person: Person) { itemPersonBinding.name.text = person.name } }
Cependant, pour créer un tel ViewHolder
devrez écrire un petit passe-partout:
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PersonViewHolder { val layoutInflater = LayoutInflater.from(parent.context) val itemPersonBinding = ItemPersonBinding.inflate(layoutInflater, parent, false) return PersonViewHolder(itemPersonBinding) }
Il serait plus pratique si, lorsque vous travaillez avec RecyclerView.ViewHolder
la méthode layoutInflater
inflate(...)
n'a pas le paramĂštre layoutInflater
, mais le reçoit du parent
passé.
Ici, il est également nécessaire de mentionner que lors de l'utilisation de la liaison de vues, la view
recherchée via findViewById()
qu'une seule fois lorsque la méthode findViewById()
est inflate()
. Cela donne un avantage sur kotlin-android-extensions
, dans lequel la mise en cache des view
par défaut ne fonctionnait que dans Activity
and Fragment
, et RecyclerView.ViewHolder
nécessitait une configuration supplémentaire .
En général, View Binding est une chose trÚs pratique qui est facile à utiliser dans les projets existants. Creator Butter Knife recommande déjà de passer à View Binding.
Il est dommage qu'un tel instrument ne soit pas apparu il y a plusieurs années.