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.
Você deve estar familiarizado com:
onCreate()
.findViewById()
para obter uma referência a uma vista.findViewById()
.findViewById()
e para acessar
dados diretamente dos arquivos XML de layout. 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:
findByView()
.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.
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.
build.gradle (Module: App)
.android
, antes da chave de fechamento, adicione uma seção
buildFeatures
e defina dataBinding
como true
. buildFeatures {
dataBinding true
}
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.
activity_main.xml
.<layout></layout>
como a etiqueta mais externa em torno de
<LinearLayout>
. <layout>
<LinearLayout ... >
...
</LinearLayout>
</layout>
<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">
Adicione uma referência ao objeto de vinculação à atividade principal, para que você possa usá-lo para acessar as vistas:
MainActivity.kt
.onCreate()
, no nível superior, crie uma variável para o objeto de vinculação. Esta
variável é normalmente chamada de binding
.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
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).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:
setContentView()
da classe DataBindingUtil
para associar o layout
activity_main
ao MainActivity
. Esta função setContentView()
também
cuida de algumas configurações de vinculação de dados para as vistas. onCreate()
, substitua a chamada setContentView()
pela seguinte linha de código.
binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
DataBindingUtil
.import androidx.databinding.DataBindingUtil
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
.
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. findViewById<Button>(R.id.
done_button
)
binding.doneButton
onCreate()
deve se parecer com isto.binding.doneButton.setOnClickListener {
addNickname(it)
}
findViewById()
na função
addNickname()
.findViewById<
View
>(R.id.
id_view
)
com binding.
idView
. Faça isso da seguinte maneira:editText
e nicknameTextView
junto com suas
chamadas para findViewById()
. Isso lhe dará erros.nicknameText
, nicknameEdit
e
doneButton
do objeto binding
em vez de variáveis (excluídas).view.visibility
por binding.doneButton.visibility
. Usando
binding.doneButton
em vez da view
passada torna o código mais consistente. binding.nicknameText.text = binding.nicknameEdit.text
binding.nicknameEdit.visibility = View.GONE
binding.doneButton.visibility = View.GONE
binding.nicknameText.visibility = View.VISIBLE
view
e
atualizar todos os usos de view
para usar binding.doneButton
dentro desta funçã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()
apply{}
. binding.apply {
nicknameText.text = nicknameEdit.text.toString()
nicknameEdit.visibility = View.GONE
doneButton.visibility = View.GONE
nicknameText.visibility = View.VISIBLE
}
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.
java
, abra o arquivo MyName.kt
. Se você não tiver
esse arquivo, crie um arquivo Kotlin e chame-o de MyName.kt
. data class MyName(var name: String = "", var nickname: String = "")
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.
activity_main.xml
na guia Text.<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.
<data>
, adicione uma etiqueta <variable>
. 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
.
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}"
Agora você tem uma referência aos dados em seu arquivo de layout. Em seguida, você cria os dados reais.
MainActivity.kt
. 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")
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
A etapa final é usar também a classe de dados para o apelido no TextView
.
activity_main.xml
.nickname_text
, adicione uma propriedade text
. Faça referência
ao nickname
na classe de dados, conforme mostrado abaixo. android:text="@={myName.nickname}"
MainActivity
, substituanicknameText.text = nicknameEdit.text.toString()
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.
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()
...
}
Projeto Android Studio: AboutMeDataBinding
Etapas para usar vinculação de dados para substituir chamadas para findViewById()
:
build.gradle
:
buildFeatures {dataBinding true}
<layout>
como a vista raiz em seu layout XML.private lateinit var binding: ActivityMainBinding
MainActivity
, substituindo
setContentView
:binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
findViewById()
por referências à vista no objeto de vinculação. Por
exemplo: findViewById<Button>(R.id.done_button)
⇒ binding.doneButton
id
da vista no XML). Etapas para vincular vistas a dados:
<data>
dentro da etiqueta <layout>
.<variable>
com um nome e um tipo que é a classe de dados. <data>
<variable
name="myName"
type="com.example.android.aboutme.MyName" />
</data>
MainActivity
, crie uma variável com uma instância da classe de dados. Por exemplo:
private val myName: MyName = MyName("Aleks Haecky")
binding.myName = myName
<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.
Por que você deseja minimizar chamadas explícitas e implícitas para findViewById()
?
findViewById()
é chamado, ele atravessa a hierarquia de vista. findViewById()
é executado na thread principal ou IU.Como você descreveria a vinculação de dados?
Por exemplo, aqui está algo que você poderia dizer sobre vinculação de dados:
Qual das opções a seguir NÃO é um benefício da vinculação de dados?
findViewById()
gera um erro do compilador.Qual é a função da etiqueta <layout>
?
<data>
dentro de um <layout>
para vincular
uma variável a uma classe de dados.Qual é a maneira correta de referenciar dados vinculados no layout XML?
android:text="@={myDataClass.property}"
android:text="@={myDataClass}"
android:text="@={myDataClass.property.toString()}"
android:text="@={myDataClass.bound_data.property}"
Comece a próxima lição:
Para obter enlaces para outros tutoriais neste curso, consulte a página de destino dos tutoriais Fundamentos de Android em Kotlin.