Classes de vinculação geradas

A Data Binding Library gera classes de vinculação que são usadas para acessar as variáveis e visualizações do layout. Esta página 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. O nome e o pacote da classe de vinculação podem ser personalizados. 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 é baseado no nome do arquivo de layout, convertido para o Pascal Case e com o sufixo Binding. O nome do arquivo de layout acima é activity_main.xml, portanto, a classe gerada correspondente é ActivityMainBinding. Essa classe mantém todas as vinculações, desde as propriedades de layout (por exemplo, a variável user) até as visualizações do layout, e sabe atribuir valores para as expressões de vinculação.

Criar um objeto de vinculação

O objeto de vinculação precisa ser criado logo após a inflação do layout para garantir que a hierarquia de visualização não seja modificada antes de ser vinculada às visualizações com expressões dentro do 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 a seguir:

Kotlin

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

        val binding: MyLayoutBinding = MyLayoutBinding.inflate(layoutInflater)
    }

    

Java

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

    

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 foi inflado usando outro mecanismo, ele pode ser vinculado separadamente da seguinte maneira:

Kotlin

    val binding: MyLayoutBinding = MyLayoutBinding.bind(viewRoot)

    

Java

    MyLayoutBinding binding = MyLayoutBinding.bind(viewRoot);

    

Às vezes, não é possível saber o tipo de vinculação com antecedência. Nesses casos, a vinculação pode ser criada 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 em um adaptador Fragment, ListView ou RecyclerView, poderá preferir usar os métodos inflate() das classes de vinculação ou da 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 Data Binding Library cria um campo imutável na classe de vinculação para cada visualização que tenha um código no layout. Por exemplo, a Data Binding Library cria os campos firstName e lastName do tipo TextView a partir do 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 que incluem os códigos da hierarquia da visualização em uma única passagem. Esse mecanismo pode ser mais rápido do que chamar o método findViewById() para todas as visualizações do layout.

Os códigos 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 às visualizações a partir do código é necessário.

Variáveis

A Data Binding Library 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 uma visualização invisível. Quando se tornam visíveis ou são explicitamente instruídos a inflarem, os objetos se substituem no layout, inflando outro layout.

Como o ViewStub basicamente desaparece da hierarquia de visualização, a visualização no objeto de vinculação também precisa desaparecer para que possa ser reivindicada pela coleta de lixo. Já que as visualizações são finais, um objeto ViewStubProxy assume o lugar do ViewStub na classe de vinculação gerada, dando acesso ao ViewStub quando ele existir e também à hierarquia de visualização inflada quando o ViewStub for inflado.

Ao inflar outro layout, uma vinculação precisa ser estabelecida para o novo layout. Portanto, o ViewStubProxy precisa ouvir o OnInflateListener ViewStub e estabelecer a vinculação quando necessário. Como somente um listener pode existir em determinado momento, o ViewStubProxy permite que você defina 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().

Vinculação avançada

Variáveis dinâmicas

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

No exemplo a seguir, todos os layouts aos quais 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

É possível mudar seu modelo de dados em uma linha de execução em segundo plano, desde que não seja uma coleção. A vinculação de dados localiza cada variável/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 os sublinhados (_), com maiúscula na letra seguinte e colocando a palavra Binding como sufixo. A classe é colocada em um pacote databinding no pacote do módulo. Por exemplo, o arquivo de layout contact_item.xml gera a classe ContactItemBinding. 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 diferentes pacotes 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>
    

É possível gerar a classe de vinculação em um pacote diferente, acrescentando um prefixo ao nome da classe com um ponto. O exemplo a seguir 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 no qual 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 vinculação de dados, consulte os seguintes recursos adicionais.

Amostras

Codelabs

Publicações do blog