Este codelab faz parte do curso Conceitos básicos do Kotlin para Android. Você vai aproveitar mais este curso se fizer os codelabs em sequência. Todos os codelabs do curso estão listados na página inicial dos codelabs de princípios básicos do Kotlin para Android.
Introdução
No codelab anterior, você atualizou o app TrackMySleepQuality para mostrar dados sobre a qualidade do sono em um RecyclerView
. As técnicas que você aprendeu ao criar seu primeiro RecyclerView
são suficientes para a maioria dos RecyclerViews
que mostram listas simples que não são muito grandes. No entanto, há várias técnicas que tornam o RecyclerView
mais eficiente para listas grandes e facilitam a manutenção e extensão do código para listas e grades complexas.
Neste codelab, você vai criar o app de rastreamento do sono do codelab anterior. Você vai aprender uma maneira mais eficaz de atualizar a lista de dados de sono e como usar a vinculação de dados com RecyclerView
. Se você não tiver o app do codelab anterior, faça o download do código inicial para este codelab.
O que você já precisa saber
- Criar uma interface básica do usuário usando uma atividade, fragmentos e visualizações.
- Navegar entre fragmentos e usar
safeArgs
para transmitir dados entre eles. - Ver modelos, fábricas de modelos, transformações,
LiveData
e os observadores deles. - Como criar um banco de dados
Room
, um DAO e definir entidades. - Como usar corrotinas para banco de dados e outras tarefas de longa duração.
- Como implementar um
RecyclerView
básico com umAdapter
,ViewHolder
e um layout de item.
O que você vai aprender
- Como usar
DiffUtil
para atualizar de forma eficiente uma lista exibida porRecyclerView
. - Como usar a vinculação de dados com
RecyclerView
. - Como usar adaptadores de vinculação para transformar dados.
Atividades deste laboratório
- Crie com base no app TrackMySleepQuality do codelab anterior desta série.
- Atualize o
SleepNightAdapter
para atualizar a lista de maneira eficiente usandoDiffUtil
. - Implemente a vinculação de dados para o
RecyclerView
usando adaptadores de vinculação para transformar os dados.
O app de monitoramento do sono tem duas telas, representadas por fragmentos, conforme mostrado na figura abaixo.
A primeira tela, mostrada à esquerda, tem botões para iniciar e interromper o rastreamento. A tela mostra alguns dos dados de sono do usuário. O botão Limpar exclui permanentemente todos os dados que o app coletou do usuário. A segunda tela, mostrada à direita, é para selecionar uma classificação de qualidade do sono.
Esse app foi arquitetado para usar um controlador de UI, ViewModel
e LiveData
, e um banco de dados Room
para manter os dados de sono.
Os dados de sono são mostrados em um RecyclerView
. Neste codelab, você vai criar a parte de vinculação de dados e DiffUtil
para o RecyclerView
. Depois deste codelab, seu app vai ter a mesma aparência, mas será mais eficiente e fácil de escalonar e manter.
Você pode continuar usando o app SleepTracker do codelab anterior ou fazer o download do app RecyclerViewDiffUtilDataBinding-Starter no GitHub.
- Se necessário, faça o download do app RecyclerViewDiffUtilDataBinding-Starter (link em inglês) no GitHub e abra o projeto no Android Studio.
- Execute o app.
- Abra o arquivo
SleepNightAdapter.kt
. - Inspecione o código para se familiarizar com a estrutura do app. Consulte o diagrama abaixo para recapitular o uso de
RecyclerView
com o padrão de adaptador para mostrar dados de sono ao usuário.
- Com base na entrada do usuário, o app cria uma lista de objetos
SleepNight
. Cada objetoSleepNight
representa uma única noite de sono, a duração e a qualidade dela. - O
SleepNightAdapter
adapta a lista de objetosSleepNight
para algo que oRecyclerView
possa usar e mostrar. - O adaptador
SleepNightAdapter
produzViewHolders
que contêm as visualizações, os dados e as metainformações para que a visualização de reciclagem mostre os dados. - O
RecyclerView
usa oSleepNightAdapter
para determinar quantos itens serão mostrados (getItemCount()
). ORecyclerView
usaonCreateViewHolder()
eonBindViewHolder()
para receber os titulares de visualização vinculados aos dados para exibição.
O método notifyDataSetChanged() é ineficiente
Para informar ao RecyclerView
que um item na lista mudou e precisa ser atualizado, o código atual chama notifyDataSetChanged()
no SleepNightAdapter
, conforme mostrado abaixo.
var data = listOf<SleepNight>()
set(value) {
field = value
notifyDataSetChanged()
}
No entanto, notifyDataSetChanged()
informa a RecyclerView
que toda a lista pode ser inválida. Como resultado, o RecyclerView
faz uma nova vinculação e redesenha todos os itens da lista, incluindo aqueles que não estão visíveis na tela. Isso é muito trabalho desnecessário. Para listas grandes ou complexas, esse processo pode levar tempo suficiente para que a tela pisque ou gagueje enquanto o usuário rola a lista.
Para corrigir esse problema, diga ao RecyclerView
exatamente o que mudou. Em seguida, o RecyclerView
pode atualizar apenas as visualizações que mudaram na tela.
O RecyclerView
tem uma API avançada para atualizar um único elemento. Você pode usar notifyItemChanged()
para informar ao RecyclerView
que um item mudou, e funções semelhantes para itens adicionados, removidos ou movidos. Você pode fazer tudo manualmente, mas essa tarefa não é trivial e pode envolver um pouco de código.
Felizmente, existe uma maneira melhor.
O DiffUtil é eficiente e faz o trabalho pesado para você
O RecyclerView
tem uma classe chamada DiffUtil
, que calcula as diferenças entre duas listas. O DiffUtil
usa uma lista antiga e uma nova para descobrir o que é diferente. Ele encontra itens que foram adicionados, removidos ou alterados. Em seguida, ele usa um algoritmo chamado Eugene W. Myers para descobrir o número mínimo de mudanças necessárias para transformar a lista antiga na nova.
Depois que o DiffUtil
descobre o que mudou, o RecyclerView
pode usar essas informações para atualizar apenas os itens que foram alterados, adicionados, removidos ou movidos, o que é muito mais eficiente do que refazer a lista inteira.
Nesta tarefa, você vai fazer upgrade do SleepNightAdapter
para usar DiffUtil
e otimizar o RecyclerView
para mudanças nos dados.
Etapa 1: implementar SleepNightDiffCallback
Para usar a funcionalidade da classe DiffUtil
, estenda DiffUtil.ItemCallback
.
- Abra
SleepNightAdapter.kt
. - Abaixo da definição completa da classe
SleepNightAdapter
, crie uma nova classe de nível superior chamadaSleepNightDiffCallback
que estendeDiffUtil.ItemCallback
. TransmitaSleepNight
como um parâmetro genérico.
class SleepNightDiffCallback : DiffUtil.ItemCallback<SleepNight>() {
}
- Coloque o cursor no nome da classe
SleepNightDiffCallback
. - Pressione
Alt+Enter
(Option+Enter
no Mac) e selecione Implementar membros. - Na caixa de diálogo exibida, pressione Shift e clique com o botão esquerdo do mouse para selecionar os métodos
areItemsTheSame()
eareContentsTheSame()
. Em seguida, clique em OK.
Isso gera stubs emSleepNightDiffCallback
para os dois métodos, como mostrado abaixo. ODiffUtil
usa esses dois métodos para descobrir como a lista e os itens mudaram.
override fun areItemsTheSame(oldItem: SleepNight, newItem: SleepNight): Boolean {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
override fun areContentsTheSame(oldItem: SleepNight, newItem: SleepNight): Boolean {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
- Em
areItemsTheSame()
, substitua oTODO
por um código que testa se os dois itensSleepNight
transmitidos,oldItem
enewItem
, são iguais. Se os itens tiverem o mesmonightId
, eles serão iguais. Portanto, retornetrue
. Caso contrário, retornefalse
. ODiffUtil
usa esse teste para ajudar a descobrir se um item foi adicionado, removido ou movido.
override fun areItemsTheSame(oldItem: SleepNight, newItem: SleepNight): Boolean {
return oldItem.nightId == newItem.nightId
}
- Em
areContentsTheSame()
, verifique seoldItem
enewItem
contêm os mesmos dados, ou seja, se são iguais. Essa verificação de igualdade vai verificar todos os campos, porqueSleepNight
é uma classe de dados. As classesData
definem automaticamenteequals
e alguns outros métodos para você. Se houver diferenças entreoldItem
enewItem
, esse código vai informar aDiffUtil
que o item foi atualizado.
override fun areContentsTheSame(oldItem: SleepNight, newItem: SleepNight): Boolean {
return oldItem == newItem
}
É comum usar um RecyclerView
para mostrar uma lista que muda. O RecyclerView
fornece uma classe de adaptador, ListAdapter
, que ajuda a criar um adaptador RecyclerView
com suporte de uma lista.
O ListAdapter
acompanha a lista e notifica o adaptador quando ela é atualizada.
Etapa 1: mudar o adaptador para estender ListAdapter
- No arquivo
SleepNightAdapter.kt
, mude a assinatura da classeSleepNightAdapter
para estenderListAdapter
. - Se solicitado, importe
androidx.recyclerview.widget.ListAdapter
. - Adicione
SleepNight
como o primeiro argumento aoListAdapter
, antes deSleepNightAdapter.ViewHolder
. - Adicione
SleepNightDiffCallback()
como um parâmetro ao construtor. OListAdapter
vai usar isso para descobrir o que mudou na lista. A assinatura da classeSleepNightAdapter
finalizada vai ficar assim:
class SleepNightAdapter : ListAdapter<SleepNight, SleepNightAdapter.ViewHolder>(SleepNightDiffCallback()) {
- Na classe
SleepNightAdapter
, exclua o campodata
, incluindo o setter. Você não precisa mais dele, porque oListAdapter
acompanha a lista para você. - Exclua a substituição de
getItemCount()
, porque oListAdapter
implementa esse método para você. - Para se livrar do erro em
onBindViewHolder()
, mude a variávelitem
. Em vez de usardata
para receber umitem
, chame o métodogetItem(position)
fornecido peloListAdapter
.
val item = getItem(position)
Etapa 2: use submitList() para manter a lista atualizada
Seu código precisa informar ao ListAdapter
quando uma lista alterada estiver disponível. O ListAdapter
fornece um método chamado submitList()
para informar ao ListAdapter
que uma nova versão da lista está disponível. Quando esse método é chamado, o ListAdapter
compara a nova lista com a antiga e detecta itens que foram adicionados, removidos, movidos ou alterados. Em seguida, o ListAdapter
atualiza os itens mostrados por RecyclerView
.
- Abra
SleepTrackerFragment.kt
. - Em
onCreateView()
, no observador emsleepTrackerViewModel
, encontre o erro em que a variáveldata
excluída é referenciada. - Substitua
adapter.data = it
por uma chamada paraadapter.submitList(it)
. Confira o código atualizado abaixo.
sleepTrackerViewModel.nights.observe(viewLifecycleOwner, Observer {
it?.let {
adapter.submitList(it)
}
})
- Execute o app. Ele vai rodar mais rápido, talvez não de forma perceptível se a lista for pequena.
Nesta tarefa, você vai usar a mesma técnica dos codelabs anteriores para configurar a vinculação de dados e eliminar as chamadas para findViewById()
.
Etapa 1: adicionar vinculação de dados ao arquivo de layout
- Abra o arquivo de layout
list_item_sleep_night.xml
na guia Texto. - Coloque o cursor na tag
ConstraintLayout
e pressioneAlt+Enter
(Option+Enter
em um Mac). O menu de intenções (menu de "correção rápida") é aberto. - Selecione Converter em layout de vinculação de dados. Isso envolve o layout em
<layout>
e adiciona uma tag<data>
dentro. - Role de volta para o topo, se necessário, e dentro da tag
<data>
, declare uma variável chamadasleep
. - Faça com que o
type
seja o nome totalmente qualificado deSleepNight
,com.example.android.trackmysleepquality.database.SleepNight
. A tag<data>
finalizada vai ficar assim:
<data>
<variable
name="sleep"
type="com.example.android.trackmysleepquality.database.SleepNight"/>
</data>
- Para forçar a criação do objeto
Binding
, selecione Build > Clean Project e depois Build > Rebuild Project. Se você ainda tiver problemas, selecione File > Invalidate Caches / Restart. O objeto de vinculaçãoListItemSleepNightBinding
, junto com o código relacionado, é adicionado aos arquivos gerados do projeto.
Etapa 2: inflar o layout do item usando a vinculação de dados
- Abra
SleepNightAdapter.kt
. - Na classe
ViewHolder
, encontre o métodofrom()
. - Exclua a declaração da variável
view
.
Código a ser excluído:
val view = layoutInflater
.inflate(R.layout.list_item_sleep_night, parent, false)
- Onde estava a variável
view
, defina uma nova variável chamadabinding
que infla o objeto de vinculaçãoListItemSleepNightBinding
, conforme mostrado abaixo. Faça a importação necessária do objeto de vinculação.
val binding =
ListItemSleepNightBinding.inflate(layoutInflater, parent, false)
- No final da função, em vez de retornar o
view
, retornebinding
.
return ViewHolder(binding)
- Para se livrar do erro, coloque o cursor na palavra
binding
. PressioneAlt+Enter
(Option+Enter
em um Mac) para abrir o menu de intenção.
- Selecione Mudar o tipo de parâmetro "itemView" do construtor principal da classe "ViewHolder" para "ListItemSleepNightBinding". Isso atualiza o tipo de parâmetro da classe
ViewHolder
.
- Role para cima até a definição da classe
ViewHolder
para ver a mudança na assinatura. Você vai encontrar um erro emitemView
porque mudouitemView
parabinding
no métodofrom()
.
Na definição da classeViewHolder
, clique com o botão direito do mouse em uma das ocorrências deitemView
e selecione Refactor > Rename. Mude o nome parabinding
. - Adicione o prefixo
val
ao parâmetro do construtorbinding
para transformá-lo em uma propriedade. - Na chamada para a classe mãe,
RecyclerView.ViewHolder
, mude o parâmetro debinding
parabinding.root
. É necessário transmitir umView
, ebinding.root
é oConstraintLayout
raiz no layout do item. - A declaração de classe finalizada vai ficar parecida com o código abaixo.
class ViewHolder private constructor(val binding: ListItemSleepNightBinding) : RecyclerView.ViewHolder(binding.root){
Você também vai encontrar um erro nas chamadas para findViewById()
, que será corrigido em seguida.
Etapa 3: substituir findViewById()
Agora é possível atualizar as propriedades sleepLength
, quality
e qualityImage
para usar o objeto binding
em vez de findViewById()
.
- Mude as inicializações de
sleepLength
,qualityString
equalityImage
para usar as visualizações do objetobinding
, conforme mostrado abaixo. Depois disso, o código não vai mais mostrar erros.
val sleepLength: TextView = binding.sleepLength
val quality: TextView = binding.qualityString
val qualityImage: ImageView = binding.qualityImage
Com o objeto de vinculação no lugar, não é mais necessário definir as propriedades sleepLength
, quality
e qualityImage
. O DataBinding
armazena em cache as pesquisas, então não é necessário declarar essas propriedades.
- Clique com o botão direito do mouse nos nomes das propriedades
sleepLength
,quality
equalityImage
. Selecione Refatorar > Inline ou pressioneControl+Command+N
(Option+Command+N
em um Mac). - Execute o app. Talvez seja necessário limpar e recompilar o projeto se ele tiver erros.
Nesta tarefa, você vai atualizar o app para usar a vinculação de dados com adaptadores de vinculação e definir os dados nas visualizações.
Em um codelab anterior, você usou a classe Transformations
para usar LiveData
e gerar strings formatadas para mostrar em visualizações de texto. No entanto, se você precisar vincular tipos diferentes ou complexos, forneça adaptadores de vinculação para ajudar a vinculação de dados a usar esses tipos. Os adaptadores de vinculação são adaptadores que pegam seus dados e os adaptam para algo que a vinculação de dados possa usar para vincular uma visualização, como texto ou uma imagem.
Você vai implementar três adaptadores de vinculação, um para a imagem de qualidade e um para cada campo de texto. Em resumo, para declarar um adaptador de vinculação, defina um método que receba um item e uma visualização e adicione a anotação @BindingAdapter
. No corpo do método, implemente a transformação. Em Kotlin, você pode escrever um adaptador de vinculação como uma função de extensão na classe de visualização que recebe os dados.
Etapa 1: criar adaptadores de vinculação
Observe que você terá que importar várias classes na etapa, e elas não serão chamadas individualmente.
- Abra
SleepNightAdapater.kt
. - Na classe
ViewHolder
, encontre o métodobind()
e lembre-se da função dele. Você vai usar o código que calcula os valores debinding.sleepLength
,binding.quality
ebinding.qualityImage
dentro do adaptador. Por enquanto, deixe o código como está. Você vai movê-lo em uma etapa posterior. - No pacote
sleeptracker
, crie e abra um arquivo chamadoBindingUtils.kt
. - Declare uma função de extensão em
TextView
, chamadasetSleepDurationFormatted
, e transmita umaSleepNight
. Essa função será seu adaptador para calcular e formatar a duração do sono.
fun TextView.setSleepDurationFormatted(item: SleepNight) {}
- No corpo de
setSleepDurationFormatted
, vincule os dados à visualização como fez emViewHolder.bind()
. ChameconvertDurationToFormatted()
e defina otext
doTextView
como o texto formatado. Como essa é uma função de extensão emTextView
, você pode acessar diretamente a propriedadetext
.
text = convertDurationToFormatted(item.startTimeMilli, item.endTimeMilli, context.resources)
- Para informar a vinculação de dados sobre esse adaptador de vinculação, faça a anotação
@BindingAdapter
na função. - Essa função é o adaptador do atributo
sleepDurationFormatted
. Portanto, transmitasleepDurationFormatted
como um argumento para@BindingAdapter
.
@BindingAdapter("sleepDurationFormatted")
- O segundo adaptador define a qualidade do sono com base no valor de um objeto
SleepNight
. Crie uma função de extensão chamadasetSleepQualityString()
emTextView
e transmita umaSleepNight
. - No corpo, vincule os dados à visualização como fez em
ViewHolder.bind()
. ChameconvertNumericQualityToString
e defina otext
. - Anote a função com
@BindingAdapter("sleepQualityString")
.
@BindingAdapter("sleepQualityString")
fun TextView.setSleepQualityString(item: SleepNight) {
text = convertNumericQualityToString(item.sleepQuality, context.resources)
}
- O terceiro adaptador de vinculação define a imagem em uma visualização de imagem. Crie a função de extensão em
ImageView
, chamesetSleepImage
e use o código deViewHolder.bind()
, conforme mostrado abaixo.
@BindingAdapter("sleepImage")
fun ImageView.setSleepImage(item: SleepNight) {
setImageResource(when (item.sleepQuality) {
0 -> R.drawable.ic_sleep_0
1 -> R.drawable.ic_sleep_1
2 -> R.drawable.ic_sleep_2
3 -> R.drawable.ic_sleep_3
4 -> R.drawable.ic_sleep_4
5 -> R.drawable.ic_sleep_5
else -> R.drawable.ic_sleep_active
})
}
Etapa 2: atualizar o SleepNightAdapter
- Abra
SleepNightAdapter.kt
. - Exclua tudo no método
bind()
, porque agora você pode usar a vinculação de dados e seus novos adaptadores para fazer esse trabalho.
fun bind(item: SleepNight) {
}
- Em
bind()
, atribua sleep aitem
, porque é necessário informar ao objeto de vinculação sobre seu novoSleepNight
.
binding.sleep = item
- Abaixo dessa linha, adicione
binding.executePendingBindings()
. Essa chamada é uma otimização que pede à vinculação de dados para executar imediatamente todas as vinculações pendentes. É sempre recomendável chamarexecutePendingBindings()
ao usar adaptadores de vinculação em umRecyclerView
, porque isso pode acelerar um pouco o dimensionamento das visualizações.
binding.executePendingBindings()
Etapa 3: adicionar vinculações ao layout XML
- Abra
list_item_sleep_night.xml
. - No
ImageView
, adicione uma propriedadeapp
com o mesmo nome do adaptador de vinculação que define a imagem. Transmita a variávelsleep
, conforme mostrado abaixo.
Essa propriedade cria a conexão entre a visualização e o objeto de vinculação pelo adaptador. Sempre quesleepImage
for referenciado, o adaptador vai adaptar os dados doSleepNight
.
app:sleepImage="@{sleep}"
- Faça o mesmo para as visualizações de texto
sleep_length
equality_string
. Sempre quesleepDurationFormatted
ousleepQualityString
forem referenciados, os adaptadores vão adaptar os dados doSleepNight
.
app:sleepDurationFormatted="@{sleep}"
app:sleepQualityString="@{sleep}"
- Execute o app. Ele vai funcionar exatamente como antes. Os adaptadores de vinculação cuidam de todo o trabalho de formatação e atualização das visualizações à medida que os dados mudam, simplificando o
ViewHolder
e ao código uma estrutura muito melhor do que antes.
Você mostrou a mesma lista nos últimos exercícios. Isso é proposital para mostrar que a interface Adapter
permite arquitetar seu código de várias maneiras diferentes. Quanto mais complexo for o código, mais importante será arquitetá-lo bem. Em apps de produção, esses e outros padrões são usados com RecyclerView
. Todos os padrões funcionam, e cada um tem seus benefícios. A escolha depende do que você está criando.
Parabéns! Agora você está no caminho certo para dominar o RecyclerView
no Android.
Projeto do Android Studio: RecyclerViewDiffUtilDataBinding.
DiffUtil
:
- O
RecyclerView
tem uma classe chamadaDiffUtil
, que calcula as diferenças entre duas listas. - O
DiffUtil
tem uma classe chamadaItemCallBack
que você estende para descobrir a diferença entre duas listas. - Na classe
ItemCallback
, substitua os métodosareItemsTheSame()
eareContentsTheSame()
.
ListAdapter
:
- Para ter um gerenciamento de listas sem custo financeiro, use a classe
ListAdapter
em vez deRecyclerView.Adapter
. No entanto, se você usarListAdapter
, vai precisar escrever seu próprio adaptador para outros layouts. Por isso, este codelab mostra como fazer isso. - Para abrir o menu de intenção no Android Studio, coloque o cursor em qualquer item de código e pressione
Alt+Enter
(Option+Enter
em um Mac). Esse menu é especialmente útil para refatorar código e criar stubs para implementar métodos. O menu é sensível ao contexto. Por isso, posicione o cursor exatamente para abrir o menu correto.
Vinculação de dados:
- Use a vinculação de dados no layout do item para vincular dados às visualizações.
Adaptadores de vinculação:
- Antes, você usou
Transformations
para criar strings com base em dados. Se você precisar vincular dados de tipos diferentes ou complexos, forneça adaptadores de vinculação para ajudar a vinculação de dados a usá-los. - Para declarar um adaptador de vinculação, defina um método que receba um item e uma visualização e anote o método com
@BindingAdapter
. No Kotlin, é possível escrever o adaptador de vinculação como uma função de extensão noView
. Transmita o nome da propriedade que o adaptador adapta. Exemplo:
@BindingAdapter("sleepDurationFormatted")
- No layout XML, defina uma propriedade
app
com o mesmo nome do adaptador de vinculação. Transmita uma variável com os dados. Exemplo:
.app:sleepDurationFormatted="@{sleep}"
Cursos da Udacity:
Documentação do desenvolvedor Android:
- Como criar uma lista com o RecyclerView
RecyclerView
DiffUtil
- Biblioteca Data Binding
- Como vincular adaptadores
notifyDataSetChanged()
Transformations
Outros recursos:
Esta seção lista as possíveis atividades de dever de casa para os alunos que estão fazendo este codelab como parte de um curso ministrado por um professor. Cabe ao professor fazer o seguinte:
- Atribuir o dever de casa, se necessário.
- Informar aos alunos como enviar deveres de casa.
- Atribuir nota aos deveres de casa.
Os professores podem usar essas sugestões o quanto quiserem, podendo passar os exercícios que acharem mais apropriados como dever de casa.
Se você estiver seguindo este codelab por conta própria, sinta-se à vontade para usar esses deveres de casa para testar seu conhecimento.
Responda estas perguntas
Pergunta 1
Quais das seguintes opções são necessárias para usar DiffUtil
? Selecione todas as opções aplicáveis.
▢ Estenda a classe ItemCallBack
.
▢ Substituir areItemsTheSame()
.
▢ Substituir areContentsTheSame()
.
▢ Use a vinculação de dados para rastrear as diferenças entre os itens.
Pergunta 2
Quais das alternativas a seguir são verdadeiras sobre os adaptadores de vinculação?
▢ Um adaptador de vinculação é uma função anotada com @BindingAdapter
.
▢ O uso de um adaptador de vinculação permite separar a formatação de dados do armazenador de visualização.
▢ Você precisa usar um RecyclerViewAdapter
se quiser usar adaptadores de vinculação.
▢ Os adaptadores de vinculação são uma boa solução quando você precisa transformar dados complexos.
Pergunta 3
Quando você deve usar Transformations
em vez de um adaptador de vinculação? Selecione todas as opções aplicáveis.
▢ Seus dados são simples.
▢ Você está formatando uma string.
▢ Sua lista é muito longa.
▢ Seu ViewHolder
contém apenas uma visualização.
Comece a próxima lição: