Introdução

Nos tutoriais anteriores deste curso, você usou a função findViewById() para obter referências às vistas. Quando seu aplicativo tem hierarquias de vistas complexas, findViewById() é caro e torna o aplicativo mais lento, pois o Android atravessa a hierarquia de vista, começando na raiz, até encontrar a vista desejada. Felizmente, existe uma maneira melhor.

Para definir dados em vistas, você usou recursos de string e definiu os dados da atividade. Seria mais eficiente se a vista conhecesse os dados. E, felizmente, novamente, isso é possível.

Neste tutorial, você aprende como usar vinculação de dados para eliminar a necessidade de findViewById(). Você também aprenderá a usar vinculação de dados para acessar dados diretamente de uma vista.

O que você já deveria saber

Você deve estar familiarizado com:

O que aprenderá

O que fará

Neste tutorial, você começa com o aplicativo AboutMe e altera o aplicativo para usar vinculação de dados. O aplicativo terá a mesma aparência quando terminar!

Aqui está o que o aplicativo AboutMe faz:

Você pode usar o código que criou no tutorial anterior ou pode baixar o código AboutMeDataBinding-Starter do GitHub.

O código que você escreveu nos tutoriais anteriores usa a função findViewById() para obter referências às vistas.

Cada vez que você usa findViewById() para procurar uma vista depois que a vista é criada ou recriada, o sistema Android atravessa a hierarquia de vistas em tempo de execução para encontrá-la. Quando seu aplicativo tem apenas um punhado de vistas, isso não é um problema. No entanto, os aplicativos de produção podem ter dezenas de vistas em um layout e, mesmo com o melhor design, haverá vistas aninhadas.

Pense em um layout linear que contém uma vista de rolagem que contém uma vista de texto. Para uma hierarquia de vistas grande ou profunda, encontrar uma vista pode levar tempo suficiente para tornar o aplicativo visivelmente lento para o usuário. Armazenando vistas em cache em variáveis ​​pode ajudar, mas você ainda precisa inicializar uma variável para cada vista, em cada namespace. Com muitas vistas e várias atividades, isso também se soma.

Uma solução é criar um objeto que contenha uma referência a cada vista. Este objeto, chamado de objeto Binding, pode ser usado por todo o seu aplicativo. Esta técnica é chamada de vinculação de dados. Depois que um objeto de vinculação for criado para seu aplicativo, você pode acessar as vistas e outros dados, por meio do objeto de vinculação, sem ter que atravessar a hierarquia de vistas ou procurar os dados.

A vinculação de dados tem os seguintes benefícios:

Nesta tarefa, você configura a vinculação de dados e usa a vinculação de dados para substituir chamadas para findViewById() por chamadas para o objeto de vinculação.

Etapa 1: Ative a vinculação de dados

Para usar a vinculação de dados, você precisa habilitar a vinculação de dados em seu arquivo Gradle, pois ela não está habilitada por padrão. Isso ocorre, pois a vinculação de dados aumenta o tempo de compilação e pode afetar o tempo de inicialização do aplicativo.

  1. Se você não tiver o aplicativo AboutMe de um tutorial anterior, obtenha o código AboutMeDataBinding-Starter do GitHub. Abra-o no Android Studio.
  2. Abra o arquivo build.gradle (Module: App).
  3. Dentro da seção android, antes da chave de fechamento, adicione uma seção buildFeatures e defina dataBinding como true.
buildFeatures {
    dataBinding true
}
  1. Quando solicitado, Sync o projeto. Se você não for solicitado, selecione File > Sync Project with Gradle Files.
  2. Você pode executar o aplicativo, mas não verá nenhuma mudança.

Etapa 2: Altere o arquivo de layout para ser utilizável com vinculação de dados

Para trabalhar com vinculação de dados, você precisa envolver seu layout XML com uma etiqueta <layout>. Isso ocorre para que a classe raiz não seja mais um grupo de vistas, mas sim um layout que contém grupos de vistas e vistas. O objeto de vinculação pode então saber sobre o layout e as vistas nele.

  1. Abra o arquivo activity_main.xml.
  2. Mude para a guia Text.
  3. Adicione <layout></layout> como a etiqueta mais externa em torno de <LinearLayout>.
<layout>
   <LinearLayout ... >
   ...
   </LinearLayout>
</layout>
  1. Escolha Code > Reformat code para corrigir o recuo do código.

    As declarações de namespace para um layout devem estar na etiqueta mais externa.
  1. Recorte as declarações de namespace de <LinearLayout> e cole-as na etiqueta <layout>. Sua etiqueta de abertura <layout> deve ser semelhante à mostrada abaixo, e a etiqueta <LinearLayout> deve conter apenas propriedades de vista.
<layout xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:app="http://schemas.android.com/apk/res-auto">
  1. Compile e execute seu aplicativo para verificar se você fez isso corretamente.

Etapa 3: Crie um objeto de vinculação na atividade principal

Adicione uma referência ao objeto de vinculação à atividade principal, para que você possa usá-lo para acessar as vistas:

  1. Abra o arquivo MainActivity.kt.
  2. Antes de onCreate(), no nível superior, crie uma variável para o objeto de vinculação. Esta variável é normalmente chamada de binding.

    O tipo de binding, a classe ActivityMainBinding, é criado pelo compilador especificamente para esta atividade principal. O nome é derivado do nome do arquivo de layout, ou seja, activity_main + Binding.
private lateinit var binding: ActivityMainBinding
  1. Se solicitado pelo Android Studio, importe ActivityMainBinding. Se você não for solicitado, clique em ActivityMainBinding e pressione Alt+Enter (Option+Enter em um Mac) para importar esta classe ausente. (Para obter mais atalhos de teclado, consulte Atalhos de teclado).

    A instrução import deve ser semelhante à mostrada abaixo.
import com.example.android.aboutme.databinding.ActivityMainBinding

Em seguida, você substitui a função setContentView() atual por uma instrução que faz o seguinte:

  1. Em onCreate(), substitua a chamada setContentView() pela seguinte linha de código.
binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
  1. Importe DataBindingUtil.
import androidx.databinding.DataBindingUtil

Etapa 4: Use o objeto de vinculação para substituir todas as chamadas para findViewById()

Agora você pode substituir todas as chamadas para findViewById() por referências às vistas que estão no objeto de vinculação. Quando o objeto de vinculação é criado, o compilador gera os nomes das vistas no objeto de vinculação a partir dos IDs das vistas no layout, convertendo-os em camel case. Assim, por exemplo, done_button é doneButton no objeto de vinculação, nickname_edit torna-se nicknameEdit e nickname_text torna-se nicknameText.

  1. Em onCreate(), substitua o código que usa findViewById() para localizar o done_button pelo código que faz referência ao botão no objeto de vinculação.

    Substitua este código: findViewById<Button>(R.id.done_button)
    com: binding.doneButton

    Seu código finalizado para definir o ouvinte de clique em onCreate() deve se parecer com isto.
binding.doneButton.setOnClickListener {
   addNickname(it)
}
  1. Faça o mesmo para todas as chamadas para findViewById() na função addNickname().
    Substitua todas as ocorrências de findViewById<View>(R.id.id_view) com binding.idView. Faça isso da seguinte maneira:
binding.nicknameText.text = binding.nicknameEdit.text
binding.nicknameEdit.visibility = View.GONE
binding.doneButton.visibility = View.GONE
binding.nicknameText.visibility = View.VISIBLE
  1. O nicknameText requer uma String e nicknameEdit.text é um Editable. Ao usar vinculação de dados, é necessário converter explicitamente o Editable em uma String.
binding.nicknameText.text = binding.nicknameEdit.text.toString()
  1. Você pode excluir as importações esmaecidas.
  2. Kotlinize a função usando apply{}.
binding.apply {
   nicknameText.text = nicknameEdit.text.toString()
   nicknameEdit.visibility = View.GONE
   doneButton.visibility = View.GONE
   nicknameText.visibility = View.VISIBLE
}
  1. Crie e execute seu aplicativo ... e ele deve ter a mesma aparência e funcionar exatamente como antes.

Você pode aproveitar as vantagens da vinculação de dados para disponibilizar uma classe de dados diretamente para uma vista. Essa técnica simplifica o código e é extremamente valiosa para tratar com casos mais complexos.

Para este exemplo, em vez de definir o nome e o apelido usando recursos de sequência, você cria uma classe de dados para o nome e o apelido. Você disponibiliza a classe de dados para a vista usando vinculação de dados.

Etapa 1: Crie a classe de dados MyName

  1. No Android Studio, no diretório java, abra o arquivo MyName.kt. Se você não tiver esse arquivo, crie um arquivo Kotlin e chame-o de MyName.kt.
  2. Defina uma classe de dados para o nome e o apelido. Use strings vazias como valores padrão.
data class MyName(var name: String = "", var nickname: String = "")

Etapa 2: Adicione dados ao layout

No arquivo activity_main.xml, o nome está atualmente definido em um TextView de um recurso de string. Você precisa substituir a referência ao nome por uma referência aos dados na classe de dados.

  1. Abra activity_main.xml na guia Text.
  2. No topo do layout, entre as etiquetas <layout> e <LinearLayout>, insira uma etiqueta <data></data>. É aqui que você conectará a vista com os dados.
<data>
  
</data>

Dentro das etiquetas de dados, você pode declarar variáveis ​​nomeadas que contêm uma referência a uma classe.

  1. Dentro da etiqueta <data>, adicione uma etiqueta <variable>.
  2. Adicione um parâmetro name para dar à variável um nome de "myName". Adicione um parâmetro type e defina o tipo para um nome qualificado da classe de dados MyName (nome do pacote + nome da variável).
<variable
       name="myName"
       type="com.example.android.aboutme.MyName" />

Agora, em vez de usar o recurso de string para o nome, você pode fazer referência à variável myName.

  1. Substitua android:text="@string/name" pelo código abaixo.

@={} é uma diretiva para obter os dados que são referenciados dentro das chaves.

myName faz referência à variável myName que você definiu anteriormente, que aponta para a classe de dados myName e busca a propriedade name da classe.

android:text="@={myName.name}"

Etapa 3: Crie os dados

Agora você tem uma referência aos dados em seu arquivo de layout. Em seguida, você cria os dados reais.

  1. Abra o arquivo MainActivity.kt.
  2. Acima de onCreate(), crie uma variável privada, também chamada de myName por convenção. Atribua à variável uma instância da classe de dados MyName, passando o nome.
private val myName: MyName = MyName("Aleks Haecky")
  1. Em onCreate(), defina o valor da variável myName no arquivo de layout para o valor da variável myName que você acabou de declarar. Você não pode acessar a variável no XML diretamente. Você precisa acessá-lo por meio do objeto de vinculação.
binding.myName = myName
  1. Isso pode mostrar um erro, pois você precisa atualizar o objeto de vinculação depois de fazer alterações. Compile seu aplicativo e o erro desaparecerá.

Etapa 4: Use a classe de dados para o apelido no TextView

A etapa final é usar também a classe de dados para o apelido no TextView.

  1. Abra activity_main.xml.
  2. Na exibição de texto nickname_text, adicione uma propriedade text. Faça referência ao nickname na classe de dados, conforme mostrado abaixo.
android:text="@={myName.nickname}"
  1. Em MainActivity, substitua
    nicknameText.text = nicknameEdit.text.toString()
    pelo código para definir o apelido em myName variável.
myName?.nickname = nicknameEdit.text.toString()

Depois que o apelido for definido, você deseja que seu código atualize a IU com os novos dados. Para fazer isso, você deve invatratar todas as expressões de vinculação para que sejam recriadas com os dados corretos.

  1. Inclua invalidateAll() após configurar o apelido para que a IU seja atualizada com o valor no objeto de vinculação atualizado.
binding.apply {
   myName?.nickname = nicknameEdit.text.toString()
   invalidateAll()
   ...
}
  1. Crie e execute seu aplicativo, e ele deve funcionar exatamente da mesma forma que antes.

Projeto Android Studio: AboutMeDataBinding

Etapas para usar vinculação de dados para substituir chamadas para findViewById():

  1. Ative a vinculação de dados na seção android do arquivo build.gradle:
    buildFeatures {dataBinding true}
  2. Use <layout> como a vista raiz em seu layout XML.
  3. Defina uma variável de vinculação:
    private lateinit var binding: ActivityMainBinding
  4. Crie um objeto de vinculação em MainActivity, substituindo setContentView:
    binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
  5. Substitua as chamadas para findViewById() por referências à vista no objeto de vinculação. Por exemplo:
    findViewById<Button>(R.id.done_button)binding.doneButton
    (No exemplo, o nome da vista é gerado usando camel case do id da vista no XML).

Etapas para vincular vistas a dados:

  1. Crie uma classe de dados para seus dados.
  2. Adicione um bloco <data> dentro da etiqueta <layout>.
  3. Defina uma <variable> com um nome e um tipo que é a classe de dados.
<data>
   <variable
       name="myName"
       type="com.example.android.aboutme.MyName" />
</data>
  1. Em MainActivity, crie uma variável com uma instância da classe de dados. Por exemplo:
    private val myName: MyName = MyName("Aleks Haecky")
  1. No objeto de vinculação, defina a variável para a variável que você acabou de criar:
    binding.myName = myName
  1. No XML, defina o conteúdo da vista para a variável que você definiu no bloco <data>. Use a notação de ponto para acessar os dados dentro da classe de dados.
    android:text="@={myName.name}"

Documentação para desenvolvimento em Android:

Esta seção lista as possíveis tarefas de casa para os alunos que estão trabalhando neste tutorial como parte de um curso ministrado por um instrutor.

Responda a essas perguntas

Pergunta 1

Por que você deseja minimizar chamadas explícitas e implícitas para findViewById()?

Pergunta 2

Como você descreveria a vinculação de dados?

Por exemplo, aqui está algo que você poderia dizer sobre vinculação de dados:

Pergunta 3

Qual das opções a seguir NÃO é um benefício da vinculação de dados?

Pergunta 4

Qual é a função da etiqueta <layout>?

Pergunta 5

Qual é a maneira correta de referenciar dados vinculados no layout XML?

Comece a próxima lição: 03.1: Criando um fragmento

Para obter enlaces para outros tutoriais neste curso, consulte a página de destino dos tutoriais Fundamentos de Android em Kotlin.