Classes de vinculação gerada

A biblioteca Data Binding gera classes de vinculação que podem ser usadas para acessar as variáveis e visualizações do layout. Esta documentação mostra como criar e personalizar as classes de vinculação geradas.

A classe de vinculação gerada vincula as variáveis de layout às visualizações dentro do layout. Você pode personalizar o nome e o pacote da vinculação. Todas as classes de vinculação geradas são herdadas da classe ViewDataBinding.

Uma classe de vinculação é gerada para cada arquivo de layout. Por padrão, o nome da classe é o nome do arquivo de layout convertido para o padrão Pascal com o sufixo Binding adicionado a ela. Por exemplo, se o nome do arquivo do layout for activity_main.xml, a classe gerada correspondente será ActivityMainBinding. Essa classe contém todas as vinculações das propriedades de layout para as visualizações e sabe como atribuir valores às expressões de vinculação.

Criar um objeto de vinculação

O objeto de vinculação é criado imediatamente após a inflação do layout para garantir que a hierarquia de visualização não seja modificada antes de se vincular às visualizações com expressões no layout. O método mais comum para vincular o objeto a um layout é usar os métodos estáticos na classe de vinculação. Você pode inflar a hierarquia de visualização e vincular o objeto a ela usando o método inflate() da classe de vinculação, conforme mostrado no exemplo abaixo:

Kotlin

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    val binding: MyLayoutBinding = MyLayoutBinding.inflate(layoutInflater)

    setContentView(binding.root)
}

Java

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    MyLayoutBinding binding = MyLayoutBinding.inflate(getLayoutInflater());

    setContentView(binding.root);
}

Há uma versão alternativa do método inflate() que usa um objeto ViewGroup, além do objeto LayoutInflater, conforme mostrado no exemplo a seguir.

Kotlin

val binding: MyLayoutBinding = MyLayoutBinding.inflate(getLayoutInflater(), viewGroup, false)

Java

MyLayoutBinding binding = MyLayoutBinding.inflate(getLayoutInflater(), viewGroup, false);

Se o layout for inflado usando um mecanismo diferente, você poderá vinculá-lo separadamente, da seguinte maneira:

Kotlin

val binding: MyLayoutBinding = MyLayoutBinding.bind(viewRoot)

Java

MyLayoutBinding binding = MyLayoutBinding.bind(viewRoot);

Às vezes, você não sabe o tipo de vinculação com antecedência. Nesses casos, você pode criar a vinculação usando a classe DataBindingUtil, conforme demonstrado no snippet de código a seguir.

Kotlin

val viewRoot = LayoutInflater.from(this).inflate(layoutId, parent, attachToParent)
val binding: ViewDataBinding? = DataBindingUtil.bind(viewRoot)

Java

View viewRoot = LayoutInflater.from(this).inflate(layoutId, parent, attachToParent);
ViewDataBinding binding = DataBindingUtil.bind(viewRoot);

Se você estiver usando itens de vinculação de dados dentro de um adaptador Fragment, ListView ou RecyclerView, talvez prefira usar os métodos inflate() das classes de vinculação ou a classe DataBindingUtil, conforme mostrado no exemplo de código a seguir.

Kotlin

val listItemBinding = ListItemBinding.inflate(layoutInflater, viewGroup, false)
// or
val listItemBinding = DataBindingUtil.inflate(layoutInflater, R.layout.list_item, viewGroup, false)

Java

ListItemBinding binding = ListItemBinding.inflate(layoutInflater, viewGroup, false);
// or
ListItemBinding binding = DataBindingUtil.inflate(layoutInflater, R.layout.list_item, viewGroup, false);

Visualizações com códigos

A biblioteca Data Binding cria um campo imutável na classe de vinculação para cada visualização que tem um ID no layout. Por exemplo, a biblioteca Data Binding cria os campos firstName e lastName do tipo TextView no seguinte layout:

<layout xmlns:android="http://schemas.android.com/apk/res/android">
   <data>
       <variable name="user" type="com.example.User"/>
   </data>
   <LinearLayout
       android:orientation="vertical"
       android:layout_width="match_parent"
       android:layout_height="match_parent">
       <TextView android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:text="@{user.firstName}"
   android:id="@+id/firstName"/>
       <TextView android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:text="@{user.lastName}"
  android:id="@+id/lastName"/>
   </LinearLayout>
</layout>

A biblioteca extrai as visualizações, incluindo os IDs, da hierarquia de visualizações em uma única passagem. Esse mecanismo pode ser mais rápido do que chamar o método findViewById() para todas as visualizações no layout.

Os IDs não são tão necessários quanto são sem a vinculação de dados, mas ainda há alguns casos em que o acesso a visualizações é necessário no código.

Variáveis

A biblioteca Data Binding gera métodos do acessador para cada variável declarada no layout. Por exemplo, o layout a seguir gera os métodos setter e getter na classe de vinculação para as variáveis user, image e note:

<data>
   <import type="android.graphics.drawable.Drawable"/>
   <variable name="user" type="com.example.User"/>
   <variable name="image" type="Drawable"/>
   <variable name="note" type="String"/>
</data>

ViewStubs

Ao contrário das visualizações normais, os objetos ViewStub começam como visualizações invisíveis. Quando ficam visíveis ou são explicitamente inflados, eles se substituem no layout inflando outro layout.

Como a ViewStub desaparece da hierarquia de visualização, a visualização no objeto de vinculação também precisa desaparecer para que ela seja reivindicada pela coleta de lixo. Como as visualizações são finais, um objeto ViewStubProxy substitui a ViewStub na classe de vinculação gerada, oferecendo acesso à ViewStub quando ela existe e à hierarquia de visualização inflada quando a ViewStub é inflada.

Ao inflar outro layout, uma vinculação precisa ser estabelecida para o novo layout. Portanto, o ViewStubProxy precisa detectar o ViewStub OnInflateListener e estabelecer a vinculação quando necessário. Como apenas um listener pode existir por vez, o ViewStubProxy permite definir um OnInflateListener, que é chamado depois que a vinculação é estabelecida.

Vinculação imediata

Quando uma variável ou um objeto observável muda, a vinculação é programada para mudar antes do próximo frame. No entanto, há momentos em que a vinculação precisa ser executada imediatamente. Para forçar a execução, use o método executePendingBindings().

Variáveis dinâmicas

Às vezes, a classe de vinculação específica é desconhecida. Por exemplo, um RecyclerView.Adapter que opera em layouts arbitrários não conhece a classe de vinculação específica. Ele precisa atribuir o valor de vinculação durante a chamada para o método onBindViewHolder().

No exemplo abaixo, todos os layouts a que o RecyclerView se vincula têm uma variável item. O objeto BindingHolder tem um método getBinding() que retorna a classe base ViewDataBinding.

Kotlin

override fun onBindViewHolder(holder: BindingHolder, position: Int) {
    item: T = items.get(position)
    holder.binding.setVariable(BR.item, item);
    holder.binding.executePendingBindings();
}

Java

public void onBindViewHolder(BindingHolder holder, int position) {
    final T item = items.get(position);
    holder.getBinding().setVariable(BR.item, item);
    holder.getBinding().executePendingBindings();
}

Linha de execução em segundo plano

Você pode mudar seu modelo de dados em uma linha de execução em segundo plano, desde que ele não seja uma coleção. A vinculação de dados localiza cada variável ou campo durante a avaliação para evitar problemas de simultaneidade.

Nomes de classes de vinculação personalizados

Por padrão, uma classe de vinculação é gerada com base no nome do arquivo de layout, começando com uma letra maiúscula, removendo sublinhados ( _), colocando em maiúscula a letra seguinte e colocando a palavra Binding como sufixo. Por exemplo, o arquivo de layout contact_item.xml gera a classe ContactItemBinding. A classe é colocada em um pacote databinding no pacote do módulo. Por exemplo, se o pacote do módulo for com.example.my.app, a classe de vinculação será colocada no pacote com.example.my.app.databinding.

As classes de vinculação podem ser renomeadas ou colocadas em pacotes diferentes ajustando o atributo class do elemento data. Por exemplo, o layout a seguir gera a classe de vinculação ContactItem no pacote databinding do módulo atual:

<data class="ContactItem">
    ...
</data>

Você pode gerar a classe de vinculação em um pacote diferente, adicionando um ponto como prefixo ao nome da classe. O exemplo abaixo gera a classe de vinculação no pacote do módulo:

<data class=".ContactItem">
    ...
</data>

Também é possível usar o nome completo do pacote em que você quer que a classe de vinculação seja gerada. O exemplo a seguir cria a classe de vinculação ContactItem no pacote com.example:

<data class="com.example.ContactItem">
    ...
</data>

Outros recursos

Para saber mais sobre a vinculação de dados, consulte os recursos adicionais a seguir.