Participe do evento ⁠#Android11: apresentação de lançamento da versão Beta no dia 3 de junho.

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 no Pascal Case e com o sufixo Binding. O nome do arquivo do layout acima é activity_main.xml, então a classe gerada correspondente é ActivityMainBinding. Essa classe contém todas as vinculações das propriedades de layout (por exemplo, a variável user) para as visualizações do layout e sabe como atribuir valores para as expressões de vinculação.

Criar um objeto de vinculação

O objeto de vinculação é criado imediatamente após inflar o 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. É possível 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)

        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 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 seguinte snippet de código:

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 DataBindingUtil, como 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 no 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 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 permitir a reivindicação pela coleta de lixo. Como as visualizações são finais, um objeto ViewStubProxy substitui o ViewStub na classe de vinculação gerada, oferecendo acesso ao ViewStub quando ele existe e também a hierarquia de visualização aumentada quando o ViewStub foi aumentado.

Ao inflar outro layout, uma vinculação precisa ser estabelecida para o novo layout. Portanto, o ViewStubProxy precisa ouvir o ViewStub OnInflateListener e estabelecer a vinculação quando necessário. Como só pode haver um listener em um determinado momento, o ViewStubProxy permite que você defina um OnInflateListener, que é chamado 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, uma operação RecyclerView.Adapter 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 ao método onBindViewHolder().

No exemplo a seguir, todos os layouts vinculados ao RecyclerView 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 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 no 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

Postagens do blog