Este tutorial ensina como usar um RecyclerView
para exibir listas de itens. Com base no aplicativo
sleep-tracker da série anterior de tutoriais, você aprende uma maneira melhor e mais versátil de exibir dados,
usando um RecyclerView
com uma arquitetura recomendada.
Você deve estar familiarizado com:
safeArgs
para passar dados entre fragmentos.LiveData
e seus
observadores.
Room
, criação de um DAO e definição de entidades.RecyclerView
com um Adapter
e um ViewHolder
para exibir
uma lista de itens. RecyclerView
para
exibir dados de qualidade do sono. Neste tutorial, você constrói a parte RecyclerView
de um aplicativo que rastreia a qualidade do
sono. O aplicativo usa um banco de dados Room
para armazenar dados de sono ao longo do tempo.
O aplicativo starter sleep-tracker possui duas telas, representadas por fragmentos, conforme mostrado na figura abaixo.
A primeira tela, mostrada à esquerda, possui botões para iniciar e parar o rastreamento. Esta tela também mostra todos os dados de sono do usuário. O botão Clear exclui permanentemente todos os dados que o aplicativo coletou para o usuário. A segunda tela, mostrada à direita, é para selecionar uma classificação de qualidade do sono.
Este aplicativo usa uma arquitetura simplificada com um controlador de IU, ViewModel
e
LiveData
. O aplicativo também usa um banco de dados Room
para tornar os dados de sono
persistentes.
A lista de noites de sono exibida na primeira tela é funcional, mas não é bonita. O aplicativo usa um formatador complexo para criar strings de texto para a vista de texto e números para a qualidade. Além disso, este design não pode ser escalado. Depois de corrigir todos esses problemas neste tutorial, o aplicativo final tem a mesma funcionalidade e a tela principal fica assim:
Exibindo uma lista ou grade de dados é uma das tarefas de IU mais comuns no Android. As listas variam de simples a muito complexas. Uma lista de vistas de texto pode mostrar dados simples, como uma lista de compras. Uma lista complexa, como uma lista anotada de destinos de férias, pode mostrar ao usuário muitos detalhes dentro de uma grade de rolagem com cabeçalhos.
Para suportar todos esses casos de uso, o Android fornece o widget RecyclerView
.
O maior benefício do RecyclerView
é que ele é muito eficiente para listas grandes:
RecyclerView
funciona apenas para processar ou desenhar itens que estão atualmente
visíveis na tela. Por exemplo, se sua lista tiver mil elementos, mas apenas 10 elementos estiverem visíveis,
RecyclerView
fará apenas o trabalho suficiente para desenhar 10 itens na tela. Quando o usuário
rola a tela, RecyclerView
descobre quais novos itens devem estar na tela e faz o trabalho
necessário para exibir esses itens. RecyclerView
economiza
muito tempo de processamento e ajuda a rolar as listas com fluidez.RecyclerView
pode atualizar aquele
item. Este é um grande ganho de eficiência ao exibir listas de itens complexos!Na sequência mostrada abaixo, você pode ver que uma vista foi preenchida com dados, ABC
. Depois
que essa vista rola para fora da tela, RecyclerView
reutiliza a vista para novos dados,
XYZ
.
Se você já viajou entre países que usam tomadas elétricas diferentes, provavelmente sabe como conectar seus dispositivos nas tomadas usando um adaptador. O adaptador permite converter um tipo de plugue em outro, o que, na verdade, converte uma interface em outra.
O padrão do adaptador na
engenharia de
software ajuda um objeto a trabalhar com outra API. RecyclerView
usa um adaptador para transformar
os dados do aplicativo em algo que o RecyclerView
pode exibir, sem alterar como o aplicativo
armazena e processa os dados. Para o aplicativo sleep-tracker, você constrói um adaptador que adapta os dados do
banco de dados Room
em algo que o RecyclerView
sabe como exibir, sem alterar o
ViewModel
.
Para exibir seus dados em um RecyclerView
, você precisa das seguintes partes:
RecyclerView
definida em seu arquivo de layout, para atuar
como um
recipiente para as vistas.ViewHolder
. Ele contém as
informações de vistas para exibir um item do layout do item. Os proprietários de vistas também adicionam
informações que o RecyclerView
usa para mover as vistas pela tela de maneira eficiente. RecyclerView
. Ele adapta os dados para que
possam ser exibidos em um ViewHolder
. Um RecyclerView
usa o adaptador para descobrir
como exibir os dados na tela.Nesta tarefa, você adiciona um RecyclerView
ao seu arquivo de layout e configura um
Adapter
para expor os dados de sono ao RecyclerView
.
Nesta etapa, você substitui o ScrollView
por um RecyclerView
no arquivo
fragment_sleep_tracker.xml
.
fragment_sleep_tracker.xml
na guia Design no Android
Studio.ScrollView
. Esta ação também exclui o
TextView
que está dentro do ScrollView
.RecyclerView
do painel Palette para o painel Component
Tree. Coloque o RecyclerView
dentro do ConstraintLayout
. recyclerview
ao seu
arquivo Gradle. Pode demorar alguns segundos e, em seguida, o aplicativo é sincronizado.build.gradle
, role até o final e observe a nova dependência, que é
semelhante ao código abaixo: implementation 'androidx.recyclerview:recyclerview:1.0.0'
fragment_sleep_tracker.xml
. RecyclerView
mostrado abaixo: <androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent" />
RecyclerView
um id
de sleep_list
. android:id="@+id/sleep_list"
RecyclerView
para ocupar a parte restante da tela dentro do
ConstraintLayout
. Para fazer isso, restrinja a parte superior do RecyclerView
ao
botão Start, a parte inferior ao botão Clear e cada lado ao pai. Defina a
largura e altura do layout como 0 dp no editor de layout ou em XML, usando o seguinte código: android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toTopOf="@+id/clear_button"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/stop_button"
RecyclerView
. Cada RecyclerView
precisa
de um gerenciador de layout que informa como posicionar itens na lista. O Android fornece um
LinearLayoutManager
, que por padrão apresenta os itens em uma lista vertical de linhas de largura
total. app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
RecyclerView
se expandisse para preencher o espaço disponível.O RecyclerView
é apenas um contêiner. Nesta etapa, você cria o layout e a infraestrutura para os
itens a serem exibidos dentro do RecyclerView
.
Para chegar a um RecyclerView
funcional o mais rápido possível, primeiro você usa um item de lista
simples que exibe apenas a qualidade do sono como um número. Para isso, você precisa de um recipiente de vistas,
TextItemViewHolder
. Você também precisa de uma vista, uma TextView
, para os dados. (Em
uma etapa posterior, você aprenderá mais sobre os recipientes de vistas e como organizar todos os dados do
sono).
text_item_view.xml
. Não importa o que você usa como elemento
raiz, pois você substituirá o código do modelo. text_item_view.xml
, exclua todo o código fornecido.TextView
com preenchimento de 16dp
no início e no final, e um tamanho
de texto de 24sp
. Deixe que a largura corresponda à do pai e a altura envolva o conteúdo. Como
essa vista é exibida dentro do RecyclerView
, você não precisa colocar a vista dentro de um
ViewGroup
.
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:textSize="24sp"
android:paddingStart="16dp"
android:paddingEnd="16dp"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
Util.kt
. Role até o final e adicione a definição mostrada abaixo, que cria a classe
TextItemViewHolder
. Coloque o código na parte inferior do arquivo, após a última chave de
fechamento. O código vai para Util.kt
, pois este recipiente de vistas é temporário e você o
substitui mais tarde.
class TextItemViewHolder(val textView: TextView): RecyclerView.ViewHolder(textView)
android.widget.TextView
e
androidx.recyclerview.widget.RecyclerView
. A principal tarefa na implementação de um RecyclerView
é criar o adaptador. Você tem um recipiente
de vistas simples para a vista do item e um layout para cada item. Agora você pode criar um adaptador. O
adaptador cria um recipiente de vistas e o preenche com dados para que o RecyclerView
exiba.
sleeptracker
, crie uma classe Kotlin chamada SleepNightAdapter
.
SleepNightAdapter
estenda RecyclerView.Adapter
. A classe é
chamada de SleepNightAdapter
, pois adapta um objeto SleepNight
em algo que o
RecyclerView
pode usar. O adaptador precisa saber qual recipiente de vistas usar, então passe
TextItemViewHolder
. Importe os componentes necessários quando solicitado e você verá um erro,
pois existem métodos obrigatórios para implementar.class SleepNightAdapter: RecyclerView.Adapter<TextItemViewHolder>() {}
SleepNightAdapter
, crie uma variável listOf
SleepNight
para armazenar os dados.var data = listOf<SleepNight>()
SleepNightAdapter
, substitua getItemCount()
para retornar o tamanho da lista de
noites de sono em data
. O RecyclerView
precisa saber quantos itens o adaptador tem
para exibir e faz isso chamando getItemCount()
. override fun getItemCount() = data.size
SleepNightAdapter
, substitua a função onBindViewHolder()
, conforme mostrado
abaixo. onBindViewHolder()
é chamada por RecyclerView
para exibir os
dados de um item da lista na posição especificada. Portanto, o método onBindViewHolder()
leva
dois argumentos: Um recipiente de vistas e uma posição dos dados a serem vinculados. Para este aplicativo, o
recipiente é o TextItemViewHolder
, e a posição é a posição na lista. override fun onBindViewHolder(holder: TextItemViewHolder, position: Int) {
}
onBindViewHolder()
, crie uma variável para um item em uma determinada posição nos
dados.
val item = data[position]
ViewHolder
que você criou tem uma propriedade chamada textView
. Dentro de
onBindViewHolder()
, defina o text
de textView
como o número da
qualidade do sono. Este código exibe apenas uma lista de números, mas este exemplo simples permite que você
veja como o adaptador obtém os dados no recipiente de vistas e na tela.holder.textView.text = item.sleepQuality.toString()
SleepNightAdapter
, substitua e implemente onCreateViewHolder()
, que é chamado
quando o RecyclerView
precisa de um recipiente de vistas para representar um item. ViewHolder
. O parâmetro parent
, que é o
grupo de vistas que mantém o recipiente da vista, é sempre o RecyclerView
. O parâmetro
viewType
é usado quando há várias vistas no mesmo RecyclerView
. Por exemplo, se você
colocar uma lista de vistas de texto, uma imagem e um vídeo no mesmo RecyclerView
, a função
onCreateViewHolder()
precisará saber qual tipo de vistas para usar.override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TextItemViewHolder {
}
onCreateViewHolder()
, crie uma instância de LayoutInflater
. context
contém informações sobre como
inflar a vista corretamente. Em um adaptador para uma vista recicladora, você sempre passa no contexto do
gripo de vistas parent
, que é o RecyclerView
. val layoutInflater = LayoutInflater.from(parent.context)
onCreateViewHolder()
, crie a view
pedindo ao layoutinflater
para
inflá-la. parent
para a vista. O
terceiro argumento, booleano, é attachToRoot
. Este argumento precisa ser false
, pois
RecyclerView
adiciona este item à hierarquia de vistas para você quando for a hora.val view = layoutInflater
.inflate(R.layout.text_item_view, parent, false) as TextView
onCreateViewHolder()
, retorne um TextItemViewHolder
feito com
view
.
return TextItemViewHolder(view)
RecyclerView
saber quando data
mudou, pois o
RecyclerView
não sabe nada sobre os dados. Ele somente conhece os recipientes de vistas que o
adaptador fornece.RecyclerView
quando os dados que ele está exibindo
foram alterados, adicione um configurador personalizado à variável data
que está no topo da
classe SleepNightAdapter
. No setter, provenha data
um novo valor e, em seguida,
chame notifyDataSetChanged()
para disparar o redesenho da lista com os novos dados.var data = listOf<SleepNight>()
set(value) {
field = value
notifyDataSetChanged()
}
O RecyclerView
precisa saber sobre o adaptador a ser usado para obter recipientes de vistas.
SleepTrackerFragment.kt
.onCreateview()
, crie um adaptador. Coloque este código após a criação do modelo
ViewModel
e antes da instrução return
.val adapter = SleepNightAdapter()
adapter
ao RecyclerView
. binding.sleepList.adapter = adapter
binding
. binding.sleepList
ou binding.FragmentSleepTrackerBinding
, invalide os
caches e reinicie. (Selecione File > Invalidate Caches / Restart).Até agora você tem um adaptador e uma maneira de obter dados do adaptador para o RecyclerView
.
Agora você precisa obter dados para o adaptador do ViewModel
.
SleepTrackerViewModel
.nights
, que armazena todas as noites de sono, que são os dados a serem
exibidos. A variável nights
é definida chamando getAllNights()
no banco de dados.
private
de nights
, pois você criará um observador que precisa acessar esta
variável. Sua declaração deve ser assim: val nights = database.getAllNights()
database
, abra o SleepDatabaseDao
. getAllNights()
. Observe que esta função retorna uma lista de valores
SleepNight
como LiveData
. Isso significa que a variável nights
contém
LiveData
que é mantido atualizado por Room
, e você pode observar nights
para saber quando muda.SleepTrackerFragment
. onCreateView()
, abaixo da criação do adapter
, crie um observador na variável
nights
. viewLifecycleOwner
do fragmento como o proprietário do
ciclo de vida, você pode ter certeza de que este observador somente estará ativo quando o
RecyclerView
estiver na tela.sleepTrackerViewModel.nights.observe(viewLifecycleOwner, Observer {
})
nights
), atribua o valor
aos data
do adaptador. Este é o código completo para o observador e configuração dos dados:sleepTrackerViewModel.nights.observe(viewLifecycleOwner, Observer {
it?.let {
adapter.data = it
}
})
RecyclerView
recicla recipientes de vistas, o que significa que ele os reutiliza.
Conforme uma vista rola para fora da tela, RecyclerView
reutiliza a vista para a vista que está
prestes a rolar na tela.
Como esses recipientes de vistas são reciclados, certifique-se de que onBindViewHolder()
defina ou
redefina quaisquer personalizações que os itens anteriores possam ter definido em um recipiente de vistas.
Por exemplo, você pode definir a cor do texto para vermelho em recipiente de vistas que possuem classificações de qualidade menores ou iguais a 1 e representam sono insatisfatório.
SleepNightAdapter
, adicione o seguinte código ao final de
onBindViewHolder()
. if (item.sleepQuality <= 1) {
holder.textView.setTextColor(Color.RED)
}
RecyclerView
reutiliza recipiente de vistas, ele eventualmente reutiliza um dos
recipientes de vistas vermelhos para uma classificação de alta qualidade. A classificação alta é exibida
erroneamente em vermelho. else
para definir a cor como preto se a qualidade
não for menor ou igual a um.if (item.sleepQuality <= 1) {
holder.textView.setTextColor(Color.RED)
} else {
holder.textView.setTextColor(Color.BLACK)
}
Parabéns! Agora você tem um RecyclerView
básico funcional.
Nesta tarefa, você substitui o recipiente de vistas simples por um que pode exibir mais dados para uma noite de sono.
O ViewHolder
simples que você adicionou ao Util.kt
apenas envolve um
TextView
em um TextItemViewHolder
.
class TextItemViewHolder(val textView: TextView): RecyclerView.ViewHolder(textView)
Então, por que o RecyclerView
não usa apenas um TextView
diretamente? Esta linha de
código fornece muitas funcionalidades. Um ViewHolder
descreve uma vista de item e metadados sobre
seu lugar no RecyclerView
. RecyclerView
depende dessa funcionalidade para posicionar
corretamente a vista conforme a lista rola e para fazer algo interessante como vistas animadas quando itens são
adicionados ou removidos no Adapter
.
Se o RecyclerView
precisar acessar as vistas armazenadas no ViewHolder
, ele pode
fazer isso usando a propriedade do do recipiente de itemView
. RecyclerView
usa itemView
ao vincular um
item a ser exibido na tela, ao desenhar decorações ao redor de uma vista como uma borda e para implementar
acessibilidade.
Nesta etapa, você cria o arquivo de layout para um item. O layout consiste em um ConstraintLayout
com um ImageView
para a qualidade do sono, um TextView
para a duração do sono e um
TextView
para a qualidade do texto. Como você já fez layouts antes, copie e cole o código XML
fornecido.
list_item_sleep_night
.
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/quality_image"
android:layout_width="@dimen/icon_size"
android:layout_height="60dp"
android:layout_marginStart="16dp"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:srcCompat="@drawable/ic_sleep_5" />
<TextView
android:id="@+id/sleep_length"
android:layout_width="0dp"
android:layout_height="20dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="16dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/quality_image"
app:layout_constraintTop_toTopOf="@+id/quality_image"
tools:text="Wednesday" />
<TextView
android:id="@+id/quality_string"
android:layout_width="0dp"
android:layout_height="20dp"
android:layout_marginTop="8dp"
app:layout_constraintEnd_toEndOf="@+id/sleep_length"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="@+id/sleep_length"
app:layout_constraintTop_toBottomOf="@+id/sleep_length"
tools:text="Excellent!!!" />
</androidx.constraintlayout.widget.ConstraintLayout>
SleepNightAdapter.kt
.SleepNightAdapter
chamada ViewHolder
e faça-a estender
RecyclerView.ViewHolder
.class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView){}
ViewHolder
, obtenha referências para as vistas. Você precisa de uma referência às
vistas que este ViewHolder
atualizará. Cada vez que você vincula este ViewHolder
,
você precisa acessar a imagem e ambas as vistas de texto. (Você converte este código para usar a vinculação de
dados posteriormente).val sleepLength: TextView = itemView.findViewById(R.id.sleep_length)
val quality: TextView = itemView.findViewById(R.id.quality_string)
val qualityImage: ImageView = itemView.findViewById(R.id.quality_image)
SleepNightAdapter
, em vez de TextItemViewHolder
, use o
SleepNightAdapter.ViewHolder
que você acabou de criar. class SleepNightAdapter: RecyclerView.Adapter<SleepNightAdapter.ViewHolder>() {
Atualize onCreateViewHolder()
:
onCreateViewHolder()
para retornar o ViewHolder
. list_item_sleep_night
.
TextView
.TextItemViewHolder
, retorne uma ViewHolder
.onCreateViewHolder()
atualizada: override fun onCreateViewHolder(
parent: ViewGroup, viewType: Int): ViewHolder {
val layoutInflater =
LayoutInflater.from(parent.context)
val view = layoutInflater
.inflate(R.layout.list_item_sleep_night,
parent, false)
return ViewHolder(view)
}
Atualize onBindViewHolder()
:
onBindViewHolder()
para que o parâmetro holder
seja um
ViewHolder
em vez de um TextItemViewHolder
.onBindViewHolder()
, exclua todo o código, exceto para a definição de
item
.
val
res
que contém uma referência aos resources
para esta
vista. val res = holder.itemView.context.resources
sleepLength
para a duração. Copie o código abaixo, que chama
uma função de formatação fornecida com o código inicial.holder.sleepLength.text = convertDurationToFormatted(item.startTimeMilli, item.endTimeMilli, res)
convertDurationToFormatted()
precisa ser definido. Abra
Util.kt
e descomente o código e as importações associadas a ele. (Selecione Code >
Comment with Line comments).onBindViewHolder()
, use convertNumericQualityToString()
para definir a
qualidade.holder.quality.text= convertNumericQualityToString(item.sleepQuality, res)
import com.example.android.trackmysleepquality.convertDurationToFormatted
import com.example.android.trackmysleepquality.convertNumericQualityToString
ic_sleep_active
é fornecido no código
inicial. holder.qualityImage.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
})
onBindViewHolder()
atualizada, configurando todos os dados para o
ViewHolder
: override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val item = data[position]
val res = holder.itemView.context.resources
holder.sleepLength.text = convertDurationToFormatted(item.startTimeMilli, item.endTimeMilli, res)
holder.quality.text= convertNumericQualityToString(item.sleepQuality, res)
holder.qualityImage.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
})
}
Seu RecyclerView
agora está completo! Você aprendeu como implementar um Adapter
e um
ViewHolder
e os colocou juntos para exibir uma lista com um RecyclerView
Adapter
.
Seu código até agora mostra o processo de criação de um adaptador e recipiente de vistas. No entanto, você pode
melhorar este código. O código a ser exibido e o código para gerenciar os proprietários de vistas são misturados
e onBindViewHolder()
sabe os detalhes sobre como atualizar o ViewHolder
.
Em um aplicativo de produção, você pode ter vários recipientes de vistas, adaptadores mais complexos e vários desenvolvedores fazendo alterações. Você deve estruturar seu código de forma que tudo relacionado a um recipiente de vistas esteja apenas no recipiente de vistas.
Nesta etapa, você refatora o código e move toda a funcionalidade do recipiente de vistas para o
ViewHolder
. O objetivo dessa refatoração não é alterar a aparência do aplicativo para o usuário,
mas tornar mais fácil e seguro para os desenvolvedores trabalharem no código. Felizmente, o Android Studio tem
ferramentas para ajudar.
SleepNightAdapter
, em onBindViewHolder()
, selecione tudo, exceto a instrução
para declarar a variável item
. bind
e aceite os parâmetros sugeridos. Clique em OK. bind()
é colocada abaixo de onBindViewHolder()
. private fun bind(holder: ViewHolder, item: SleepNight) {
val res = holder.itemView.context.resources
holder.sleepLength.text = convertDurationToFormatted(item.startTimeMilli, item.endTimeMilli, res)
holder.quality.text = convertNumericQualityToString(item.sleepQuality, res)
holder.qualityImage.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
})
}
holder
do parâmetro holder
de bind()
.
Pressione Alt+Enter
(Option+Enter
em um Mac) para abrir o menu de intenção.
Selecione Convert parameter to receiver para convertê-lo em uma função de extensão que tenha
a seguinte assinatura:private fun ViewHolder.bind(item: SleepNight) {...}
bind()
no ViewHolder
.bind()
público.bind()
para o adaptador, se necessário. ViewHolder
, você pode remover a parte ViewHolder
da assinatura.
Aqui está o código final para a função bind()
na classe ViewHolder
.
fun bind(item: SleepNight) {
val res = itemView.context.resources
sleepLength.text = convertDurationToFormatted(
item.startTimeMilli, item.endTimeMilli, res)
quality.text = convertNumericQualityToString(
item.sleepQuality, res)
qualityImage.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
})
}
O método onCreateViewHolder()
no adaptador atualmente infla a vista do recurso de layout para o
ViewHolder
. No entanto, a inflação não tem nada a ver com o adaptador e tudo a ver com o
ViewHolder
. A inflação deve acontecer no ViewHolder
.
onCreateViewHolder()
, selecione todo o código no corpo da função. from
e aceite os parâmetros sugeridos. Clique em OK.from
. Pressione Alt+Enter
(Option+Enter
em um Mac) para abrir o menu de intenção.from()
precisa estar em um objeto
complementar para que possa ser chamada na classe ViewHolder
, não chamada em uma instância de
ViewHolder
. companion
para a classe ViewHolder
. from()
público.onCreateViewHolder()
, altere a instrução return
para retornar o resultado da
chamada de from()
na classe ViewHolder
.onCreateViewHolder()
e from()
concluídos devem ser semelhantes ao código abaixo, e
seu código deve ser construído e executado sem erros. override fun onCreateViewHolder(parent: ViewGroup, viewType:
Int): ViewHolder {
return ViewHolder.from(parent)
}
companion object {
fun from(parent: ViewGroup): ViewHolder {
val layoutInflater = LayoutInflater.from(parent.context)
val view = layoutInflater
.inflate(R.layout.list_item_sleep_night, parent, false)
return ViewHolder(view)
}
}
ViewHolder
para que o construtor seja privado. Como
from()
agora é um método que retorna uma nova instância de ViewHolder
, não há mais
razão para ninguém chamar o construtor de ViewHolder
.class ViewHolder private constructor(itemView: View) : RecyclerView.ViewHolder(itemView){
Projeto Android Studio: RecyclerViewFundamentals
RecyclerView
foi projetado para ser eficiente mesmo ao exibir listas extremamente grandes.RecyclerView
faz apenas o trabalho necessário para processar ou desenhar itens que estão
atualmente visíveis na tela.RecyclerView
usa um adaptador para
transformar os dados do aplicativo em algo que possa exibir, sem a necessidade de alterar a forma como o
aplicativo armazena e processa os dados.Para exibir seus dados em um RecyclerView
, você precisa das seguintes partes:
RecyclerView
, defina um elemento
<RecyclerView>
no
arquivo de layout.RecyclerView
usa um LayoutManager
para
organizar o layout dos itens no RecyclerView
, como colocando-os em uma grade ou em uma lista
linear.<RecyclerView>
no arquivo de layout, defina o atributo
app:layoutManager
para o gerenciador de layout (como LinearLayoutManager
ou
GridLayoutManager
). LayoutManager
para um
RecyclerView
programaticamente. (Esta técnica é abordada em um tutorial posterior).ViewHolder
. Associe o adaptador ao RecyclerView
. RecyclerView
é executado, ele usará o adaptador para descobrir como exibir os dados na
tela.getItemCount()
para retornar o número de itens.onCreateViewHolder()
para retornar o
ViewHolder
para um item em a lista.onBindViewHolder()
para adaptar os dados às
vistas de um item da lista.ViewHolder
contém as informações de vistas para exibir um
item do layout do item. onBindViewHolder()
no adaptador adapta os dados às vistas. Você sempre substitui esse
método. Normalmente, onBindViewHolder()
infla o layout de um item e coloca os dados nas vistas do
layout. RecyclerView
não sabe nada sobre os dados, o Adapter
precisa informar o
RecyclerView
quando esses dados mudam. Use notifyDataSetChanged()
para notificar o
Adapter
que os dados foram alterados. 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.
Como o RecyclerView
exibe os itens? Selecione tudo que se aplica.
▢ Exibe itens em uma lista ou grade.
▢ Rola verticalmente ou horizontalmente.
▢ Rola diagonalmente em dispositivos maiores, como tablets.
▢ Permite layouts personalizados quando uma lista ou grade não é suficiente para o caso de uso.
Quais são os benefícios de usar o RecyclerView
? Selecione tudo que se aplica.
▢ Exibe listas grandes com eficiência.
▢ Atualiza os dados automaticamente.
▢ Minimiza a necessidade de atualizações quando um item é atualizado, excluído ou adicionado à lista.
▢ Reutiliza a vista que rola para fora da tela para exibir o próximo item que rola na tela.
Quais são algumas das razões para usar adaptadores? Selecione tudo que se aplica.
▢ A separação de interesses torna mais fácil alterar e testar o código.
▢ RecyclerView
é independente dos dados que estão sendo exibidos.
▢ As camadas de processamento de dados não precisam se preocupar com a forma como os dados serão exibidos.
▢ O aplicativo será executado mais rápido.
Quais das seguintes afirmações são verdadeiras para ViewHolder
? Selecione tudo que se aplica.
▢ O layout ViewHolder
é definido em arquivos de layout XML.
▢ Há um ViewHolder
para cada unidade de dados no conjunto de dados.
▢ Você pode ter mais de um ViewHolder
em um RecyclerView
.
▢ O Adapter
vincula os dados ao ViewHolder
.
Comece a próxima lição: