El enlace de vistas tan esperado en Android

Hace un par de días, Google lanzó Android Studio 3.6 Canary 11, la principal innovación en la que se encontraba View Binding, que se describió en mayo en Google I / O 2019.



View Binding es una herramienta que facilita la escritura de código para interactuar con la vista. Cuando habilita el enlace de vista en un módulo específico, genera clases de enlace para cada archivo de diseño en el módulo. El objeto de clase de enlace generado contiene enlaces a todas las vistas desde el archivo de marcado para el que se especifica android:id .


Cómo habilitar


Para habilitar el enlace de vista en el módulo, debe agregar un elemento al archivo build.gradle :


 android { ... viewBinding { enabled = true } } 

También puede especificar que no necesita generar una clase de enlace para un archivo de marcado particular. Para hacer esto, debe especificar el atributo de tools:viewBindingIgnore="true" en la vista raíz en el archivo de marcado deseado.


Como usar


Cada clase de enlace generada contiene un enlace a la vista raíz del marcado ( root ) y enlaces a todas las vistas que tienen una identificación. El nombre de la clase generada se forma como "nombre de archivo de marcado" traducido a mayúsculas y minúsculas + "Enlace".


Por ejemplo, para el archivo de marcado result_profile.xml :


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

Se ResultProfileBinding clase ResultProfileBinding , que contiene 2 campos: TextView name y Button button . Para ImageView no se generará nada, ya que no tiene id . También en la clase ResultProfileBinding habrá un método getRoot() que devuelve la raíz LinearLayout .


Para crear un objeto de clase ResultProfileBinding , debe llamar al método estático inflate() . Después de eso, puede usar la vista raíz como content view en la Activity :


 private lateinit var binding: ResultProfileBinding @Override fun onCreate(savedInstanceState: Bundle) { super.onCreate(savedInstanceState) binding = ResultProfileBinding.inflate(layoutInflater) setContentView(binding.root) } 

El binding posterior se puede utilizar para obtener una vista:


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

Diferencias con otros enfoques.


Las principales ventajas de View Binding son la seguridad nula y la seguridad tipo.


Al mismo tiempo, si alguna vista está disponible en un diseño de diseño, pero no en otro ( layout-land , por ejemplo), se @Nullable un campo @Nullable para él en la clase de enlace.


Además, si en diferentes configuraciones de marcado hay una vista con la misma identificación, pero diferentes tipos, se generará un campo con el tipo android.view.View para ellos.
(Al menos en la versión 3.6 de Canary 11)


En general, sería conveniente que el campo generado tuviera el tipo específico más posible. Por ejemplo, para un Button en una configuración y un TextView en otro, TextView genera un campo de tipo TextView ( public class Button extends TextView ).


Al usar el enlace de vista, todas las inconsistencias entre el marcado y el código se detectarán en la etapa de compilación, lo que evitará errores innecesarios durante el funcionamiento de la aplicación.


Uso en RecyclerView.ViewHolder


Nada impide usar el enlace de vista al crear una view para un RecyclerView.ViewHolder :


 class PersonViewHolder(private val itemPersonBinding: ItemPersonBinding) : RecyclerView.ViewHolder(itemPersonBinding.root) { fun bind(person: Person) { itemPersonBinding.name.text = person.name } } 

Sin embargo, para crear tal ViewHolder tendrá que escribir una pequeña plantilla:


 override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PersonViewHolder { val layoutInflater = LayoutInflater.from(parent.context) val itemPersonBinding = ItemPersonBinding.inflate(layoutInflater, parent, false) return PersonViewHolder(itemPersonBinding) } 

Sería más conveniente si, al trabajar con RecyclerView.ViewHolder el método inflate(...) no tendrá el parámetro layoutInflater , pero lo recibirá del parent pasado.


Aquí también vale la pena mencionar que cuando se usa el enlace de vista, la view busca a través de findViewById() solo una vez cuando se inflate() método findViewById() . Esto ofrece una ventaja sobre las kotlin-android-extensions , en las que el almacenamiento en caché de la view solo funcionaba en Activity and Fragment , y RecyclerView.ViewHolder requería una configuración adicional .


En general, View Binding es una cosa muy conveniente que es fácil de comenzar a usar en proyectos existentes. Creator Butter Knife ya recomienda cambiar a View Binding.


Es una pena que tal instrumento no apareciera hace varios años.

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


All Articles