No tutorial anterior, você aprendeu como obter dados de um serviço da web e analisar a resposta em um objeto
de dados. Neste tutorial, você se baseia nesse conhecimento para carregar e exibir fotos de um URL da web.
Você também revisará como construir um RecyclerView
e usá-lo para exibir uma grade de imagens
na página de visão geral.
LiveData
.RecyclerView
.Adapter
, ViewHolder
e DiffUtil
.RecyclerView
e um adaptador de grade para exibir uma grade de imagens. RecyclerView
para exibir uma grade de imagens de propriedades de Marte. RecyclerView
.Neste tutorial (e tutoriais relacionados), você trabalha com um aplicativo chamado MarsRealEstate, que mostra propriedades à venda em Marte. O aplicativo se conecta a um servidor de Internet para recuperar e exibir dados de propriedade, incluindo detalhes como o preço e se a propriedade está disponível para venda ou aluguel. As imagens que representam cada propriedade são fotos da vida real de Marte, capturadas pelos robôs de Marte da NASA.
A versão do aplicativo que você constrói neste tutorial preenche a página de visão geral, que exibe uma
grade de imagens. As imagens são parte dos dados de propriedade que seu aplicativo obtém do serviço da web
de imóveis da Mars. Seu aplicativo usará a biblioteca Glide para carregar e exibir as imagens e um
RecyclerView
para criar o layout de grade para as imagens. Seu aplicativo também tratará com
erros de rede normalmente.
Exibindo uma foto de um URL da web pode parecer simples, mas há um pouco de engenharia para que funcione bem. A imagem deve ser baixada, armazenada em buffer e decodificada de seu formato compactado para uma imagem que o Android possa usar. A imagem deve ser armazenada em cache na memória, um cache baseado em armazenamento ou ambos. Tudo isso precisa acontecer em threads de fundo de baixa prioridade para que a IU permaneça responsiva. Além disso, para obter o melhor desempenho da rede e da CPU, você pode buscar e decodificar mais de uma imagem de uma vez. Aprendendo como carregar imagens da rede de maneira eficaz pode ser um tutorial em si.
Felizmente, você pode usar uma biblioteca desenvolvida pela comunidade chamada Glide para baixar, armazenar em buffer, decodificar e armazenar em cache suas imagens. O Glide deixa você com muito menos trabalho do que se você tivesse que fazer tudo isso do zero.
O Glide precisa basicamente de dois argumentos:
ImageView
para exibir essa imagem. Nesta tarefa, você aprenderá a usar o Glide para exibir uma única imagem do serviço da web de imóveis. Você exibe a imagem que representa a primeira propriedade de Marte na lista de propriedades que o serviço da web retorna. Aqui estão as capturas de tela de antes e depois:
dependencies
, adicione esta linha para a biblioteca Glide: implementation "com.github.bumptech.glide:glide:$version_glide"
Observe que o número da versão já está definido separadamente no arquivo do projeto Gradle.
Em seguida, você atualiza a classe OverviewViewModel
para incluir dados ativos para uma única
propriedade de Marte.
overview/OverviewViewModel.kt
. Logo abaixo de LiveData
para a
_response
, adicione dados ativos internos (mutáveis) e externos (imutáveis) para um único
objeto MarsProperty
. MarsProperty
(com.example.android.marsrealestate.network.MarsProperty
) quando solicitado. private val _property = MutableLiveData<MarsProperty>()
val property: LiveData<MarsProperty>
get() = _property
getMarsRealEstateProperties()
, encontre a linha dentro do bloco
try/catch {}
que define _response.value
para o número de propriedades. Adicione
o teste mostrado abaixo. Se os objetos MarsProperty
estiverem disponíveis, este teste define
o valor de _property
LiveData
para a primeira propriedade em
listResult
. if (listResult.size > 0) {
_property.value = listResult[0]
}
O bloco try/catch {}
completo agora se parece com isto:
try {
val listResult = MarsApi.retrofitService.getProperties()
_response.value = "Success: ${listResult.size} Mars properties retrieved"
if (listResult.size > 0) {
_property.value = listResult[0]
}
} catch (e: Exception) {
_response.value = "Failure: ${e.message}"
}
res/layout/fragment_overview.xml
. No elemento <TextView>
,
altere android:text
para vincular ao componente imgSrcUrl
da propriedade
property
LiveData
:android:text="@{viewModel.property.imgSrcUrl}"
TextView
exibe apenas o URL da imagem na primeira propriedade de
Marte. Tudo o que você fez até agora foi configurar o modelo de vistas e os dados ativos para esse URL.
Agora você tem a URL de uma imagem para exibir e é hora de começar a trabalhar com o Glide para carregar
essa imagem. Nesta etapa, você usa um adaptador de vinculação para obter a URL de um atributo XML associado a um
ImageView
e usa o Glide para carregar a imagem. Adaptadores de vinculação são métodos de
extensão que ficam entre uma exibição e os dados associados para fornecer um comportamento personalizado
quando os dados são alterados. Nesse caso, o comportamento personalizado é chamar o Glide para carregar uma
imagem de um URL em um ImageView
.
BindingAdapters.kt
. Este arquivo conterá os adaptadores de vinculação que você usa em
todo o aplicativo. bindImage()
que recebe uma ImageView
e uma String
como parâmetros. Anote a função com @BindingAdapter
. A anotação @BindingAdapter
informa à vinculação de dados que você deseja que este adaptador de vinculação seja executado quando um
item XML tiver o atributo imageUrl
. androidx.databinding.BindingAdapter
e android.widget.ImageView
quando
solicitado.@BindingAdapter("imageUrl")
fun bindImage(imgView: ImageView, imgUrl: String?) {
}
bindImage()
, adicione um bloco let {}
para o argumento
imgUrl
:imgUrl?.let {
}
let {}
, adicione a linha mostrada abaixo para converter a string de URL (do
XML) em um objeto Uri
. Importe androidx.core.net.toUri
quando
solicitado.Uri
final use o esquema HTTPS, pois o servidor
que extrai as imagens de requer esse esquema. Para usar o esquema HTTPS, anexe
buildUpon.scheme("https")
ao construtor toUri
. O método toUri()
é
uma função de extensão Kotlin da biblioteca principal do Android KTX, então parece que faz parte da
classe String
.val imgUri = imgUrl.toUri().buildUpon().scheme("https").build()
let {}
, chame Glide.with()
para carregar a imagem do objeto
Uri
no ImageView
. Importe com.bumptech.glide.Glide
quando
solicitado.Glide.with(imgView.context)
.load(imgUri)
.into(imgView)
Embora o Glide tenha carregado a imagem, não há nada para ver ainda. A próxima etapa é atualizar o layout e
os fragmentos com um ImageView
para exibir a imagem.
res/layout/gridview_item.xml
. Este é o arquivo de recurso de layout que você usará
para cada item no RecyclerView
posteriormente no tutorial. Você o usa temporariamente aqui
para mostrar apenas uma única imagem.<ImageView>
, adicione um elemento <data>
para a
vinculação de dados e vincule à classe OverviewViewModel
: <data>
<variable
name="viewModel"
type="com.example.android.marsrealestate.overview.OverviewViewModel" />
</data>
app:imageUrl
ao elemento ImageView
para usar o novo
adaptador de vinculação de carregamento de imagem:app:imageUrl="@{viewModel.property.imgSrcUrl}"
overview/OverviewFragment.kt
. No método onCreateView()
, comente a linha
que infla a classe FragmentOverviewBinding
e a atribui à variável de vinculação. Isso é
apenas temporário; você voltará a ele mais tarde. //val binding = FragmentOverviewBinding.inflate(inflater)
GridViewItemBinding
. Importe
com.example.android.marsrealestate. databinding.GridViewItemBinding
quando solicitado. val binding = GridViewItemBinding.inflate(inflater)
MarsProperty
na
lista de resultados. O Glide pode melhorar a experiência do usuário, mostrando um espaço reservado para imagem ao carregar a imagem e uma imagem de erro se o carregamento falhar, por exemplo, se a imagem estiver faltando ou corrompida. Nesta etapa, você adiciona essa funcionalidade ao adaptador de vinculação e ao layout.
res/drawable/ic_broken_image.xml
e clique na guia Preview à direita.
Para a imagem de erro, você está usando o ícone de imagem quebrada que está disponível na biblioteca de
ícones integrada. Este drawable vetorial usa o atributo android:tint
para colorir o ícone de
cinza.
res/drawable/loading_animation.xml
. Este drawable é uma animação definida com a
etiqueta <animate-rotate>
. A animação gira um drawable de imagem,
loading_img.xml
, em torno do ponto central. (Você não vê a animação na prévia).
BindingAdapters.kt
. No método bindImage()
, atualize a
chamada para Glide.with()
para chamar a função apply()
entre
load()
e into()
. Importe com.bumptech.glide.request.RequestOptions
quando solicitado.loading_animation
). O código também define uma imagem a ser usada
se o carregamento da imagem falhar (o drawable broken_image
). O método
bindImage()
completo agora se parece com isto:
@BindingAdapter("imageUrl")
fun bindImage(imgView: ImageView, imgUrl: String?) {
imgUrl?.let {
val imgUri =
imgUrl.toUri().buildUpon().scheme("https").build()
Glide.with(imgView.context)
.load(imgUri)
.apply(RequestOptions()
.placeholder(R.drawable.loading_animation)
.error(R.drawable.ic_broken_image))
.into(imgView)
}
}
Seu aplicativo agora carrega informações de propriedade da Internet. Usando dados do primeiro item da lista
MarsProperty
, você criou uma propriedade LiveData
no modelo de vistas e usou o URL
da imagem desses dados de propriedade para preencher um ImageView
. Mas o objetivo é que seu
aplicativo exiba uma grade de imagens, então você deseja usar um RecyclerView
com um
GridLayoutManager
.
No momento, o modelo de vistas tem uma _property
LiveData
que contém um objeto
MarsProperty
- o primeiro na lista de respostas do serviço da web. Nesta etapa, você altera o
LiveData
para conter a lista inteira de objetos MarsProperty
.
overview/OverviewViewModel.kt
._property
para _properties
. Mude o tipo para uma
lista de objetos MarsProperty
. private val _properties = MutableLiveData<List<MarsProperty>>()
property
dados ativos externos por properties
. Adicione a lista
ao tipo LiveData
aqui também: val properties: LiveData<List<MarsProperty>>
get() = _properties
getMarsRealEstateProperties()
. Dentro do bloco
try {}
, substitua todo o teste que você adicionou na tarefa anterior pela linha mostrada
abaixo. Porque o
MarsApi.
retrofitService
.getProperties()
retorna uma lista de objetos MarsProperty
, você pode apenas atribuí-la a
_properties.value
em vez de testar uma resposta bem-sucedida.
_properties.value = MarsApi.retrofitService.getProperties()
O bloco try/catch
inteiro agora se parece com isto:
try {
_properties.value = MarsApi.retrofitService.getProperties()
_response.value = "Success: Mars properties retrieved"
} catch (e: Exception) {
_response.value = "Failure: ${e.message}"
}
A próxima etapa é alterar o layout e os fragmentos do aplicativo para usar uma vista de reciclagem e um layout de grade, em vez da vista de imagem única.
res/layout/gridview_item.xml
. Altere a vinculação de dados de
OverviewViewModel
para MarsProperty
e renomeie a variável para
"property"
. <variable
name="property"
type="com.example.android.marsrealestate.network.MarsProperty" />
<ImageView>
, altere o atributo app:imageUrl
para referir-se ao URL da
imagem no objeto MarsProperty
:app:imageUrl="@{property.imgSrcUrl}"
overview/OverviewFragment.kt
. Em onCreateview()
, descomente a linha que
infla FragmentOverviewBinding
. Exclua ou comente a linha que infla
GridViewBinding
. Essas alterações desfazem as alterações temporárias feitas na última
tarefa. val binding = FragmentOverviewBinding.inflate(inflater)
// val binding = GridViewItemBinding.inflate(inflater)
res/layout/fragment_overview.xml
. Exclua todo o elemento
<TextView>
. <RecyclerView>
, que usa um GridLayoutManager
e o
layout grid_view_item
para um único item:<androidx.recyclerview.widget.RecyclerView
android:id="@+id/photos_grid"
android:layout_width="0dp"
android:layout_height="0dp"
android:padding="6dp"
android:clipToPadding="false"
app:layoutManager=
"androidx.recyclerview.widget.GridLayoutManager"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:spanCount="2"
tools:itemCount="16"
tools:listitem="@layout/grid_view_item" />
Agora, o layout fragment_overview
tem um RecyclerView
, enquanto o layout
grid_view_item
tem um único ImageView
. Nesta etapa, você vincula os dados ao
RecyclerView
por meio de um adaptador RecyclerView
.
overview/PhotoGridAdapter.kt
. PhotoGridAdapter
, com os parâmetros do construtor mostrados abaixo. A classe
PhotoGridAdapter
estende ListAdapter
, cujo construtor precisa do tipo de item
de lista, o recipiente de vistas e uma implementação DiffUtil.ItemCallback
. androidx.recyclerview.widget.ListAdapter
e
com.example.android.marsrealestate.network.MarsProperty
quando solicitado. Nas etapas a
seguir, você implementa as outras partes ausentes desse construtor que estão produzindo erros.
class PhotoGridAdapter : ListAdapter<MarsProperty,
PhotoGridAdapter.MarsPropertyViewHolder>(DiffCallback) {
}
PhotoGridAdapter
e pressione Control+i
para
implementar os métodos ListAdapter
, que são onCreateViewHolder()
e
onBindViewHolder()
.override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PhotoGridAdapter.MarsPropertyViewHolder {
TODO("not implemented")
}
override fun onBindViewHolder(holder: PhotoGridAdapter.MarsPropertyViewHolder, position: Int) {
TODO("not implemented")
}
PhotoGridAdapter
, após os métodos que você acabou de
adicionar, adicione uma definição de objeto complementar para DiffCallback
, conforme
mostrado abaixo. androidx.recyclerview.widget.DiffUtil
quando solicitado.
DiffCallback
estende DiffUtil.ItemCallback
com o tipo de
objeto que você deseja comparar—MarsProperty
.companion object DiffCallback : DiffUtil.ItemCallback<MarsProperty>() {
}
Control+i
para implementar os métodos comparadores para este objeto, que são
areItemsTheSame()
e areContentsTheSame()
. override fun areItemsTheSame(oldItem: MarsProperty, newItem: MarsProperty): Boolean {
TODO("not implemented")
}
override fun areContentsTheSame(oldItem: MarsProperty, newItem: MarsProperty): Boolean {
TODO("not implemented") }
areItemsTheSame()
, remova o TODO. Use o operador de igualdade referencial de
Kotlin (===
), que retorna true
se o objeto fizer referência a
oldItem
e newItem
são os mesmos.override fun areItemsTheSame(oldItem: MarsProperty,
newItem: MarsProperty): Boolean {
return oldItem === newItem
}
areContentsTheSame()
, use o operador de igualdade padrão apenas no ID de
oldItem
e newItem
. override fun areContentsTheSame(oldItem: MarsProperty,
newItem: MarsProperty): Boolean {
return oldItem.id == newItem.id
}
PhotoGridAdapter
, abaixo do objeto complementar, adicione uma
definição de classe interna para MarsPropertyViewHolder
, que estende
RecyclerView.ViewHolder
.androidx.recyclerview.widget.RecyclerView
e
com.example.android.marsrealestate.databinding.GridViewItemBinding
quando
solicitado.GridViewItemBinding
variável para vincular a
MarsProperty
ao layout, então passe a variável para MarsPropertyViewHolder
.
Como a classe base ViewHolder
requer uma vista em seu construtor, você passa a ela a vista
raiz da vinculação. class MarsPropertyViewHolder(private var binding:
GridViewItemBinding):
RecyclerView.ViewHolder(binding.root) {
}
MarsPropertyViewHolder
, crie um método bind()
que recebe um objeto
MarsProperty
como argumento e define binding.property
para esse objeto. Chame
executePendingBindings()
depois de definir a propriedade, o que faz com que a atualização
seja executada imediatamente. fun bind(marsProperty: MarsProperty) {
binding.property = marsProperty
binding.executePendingBindings()
}
onCreateViewHolder()
, remova o TODO e adicione a linha mostrada abaixo. Importe
android.view.LayoutInflater
quando solicitado. onCreateViewHolder()
precisa retornar um novo MarsPropertyViewHolder
, criado
inflando o GridViewItemBinding
e usando o LayoutInflater
de seu contexto
ViewGroup
pai. return MarsPropertyViewHolder(GridViewItemBinding.inflate(
LayoutInflater.from(parent.context)))
onBindViewHolder()
, remova o TODO e adicione as linhas mostradas abaixo. Aqui
você chama getItem()
para obter o objeto MarsProperty
associado à posição
RecyclerView
atual e, em seguida, passa essa propriedade para o vínculo ()
método no MarsPropertyViewHolder
. val marsProperty = getItem(position)
holder.bind(marsProperty)
Finalmente, use um BindingAdapter
para inicializar o PhotoGridAdapter
com a lista
de objetos MarsProperty
. Use um BindingAdapter
para definir os dados
RecyclerView
faz com que a vinculação de dados observe automaticamente o LiveData
para a lista de objetos MarsProperty
. Em seguida, o adaptador de vinculação é chamado
automaticamente quando a lista MarsProperty
muda.
BindingAdapters.kt
. bindRecyclerView()
que recebe um
RecyclerView
e uma lista de objetos MarsProperty
como argumentos. Anote esse
método com um @BindingAdapter
. androidx.recyclerview.widget.RecyclerView
e
com.example.android.marsrealestate.network.MarsProperty
quando solicitado.@BindingAdapter("listData")
fun bindRecyclerView(recyclerView: RecyclerView,
data: List<MarsProperty>?) {
}
bindRecyclerView()
, converta recyclerView.adapter
para
PhotoGridAdapter
e chame adapter.submitList()
com os dados. Isso informa ao
RecyclerView
quando uma nova lista está disponível. Importe com.example.android.marsrealestate.overview.PhotoGridAdapter
quando solicitado.
val adapter = recyclerView.adapter as PhotoGridAdapter
adapter.submitList(data)
res/layout/fragment_overview.xml
. Adicione o atributo app:listData
ao
elemento RecyclerView
e defina-o como viewmodel.properties
usando vinculação de
dados.
app:listData="@{viewModel.properties}"
overview/OverviewFragment.kt
. Em onCreateView()
, logo antes da chamada
para setHasOptionsMenu()
, inicialize o adaptador RecyclerView
em
binding.photosGrid
para um novo objeto PhotoGridAdapter
.binding.photosGrid.adapter = PhotoGridAdapter()
MarsProperty
. Conforme você rola
para ver novas imagens, o aplicativo mostra o ícone de progresso de carregamento antes de exibir a
própria imagem. Se você ativar o modo avião, as imagens que ainda não foram carregadas aparecem como
ícones de imagem quebrada.O aplicativo MarsRealEstate exibe o ícone de imagem quebrada quando uma imagem não pode ser buscada. Mas quando não há rede, o aplicativo mostra uma tela em branco.
Esta não é uma ótima experiência do usuário. Nesta tarefa, você adiciona tratamento básico de erros, para
dar ao usuário uma ideia melhor do que está acontecendo. Se a Internet não estiver disponível, o aplicativo
mostrará o ícone de erro de conexão. Enquanto o aplicativo busca a lista MarsProperty
, o
aplicativo mostra a animação de carregamento.
Para começar, você cria um LiveData
no modelo de vistas para representar o status da
solicitação da web. Existem três estados a serem considerados - carregamento, sucesso e falha. O estado de
carregamento ocorre enquanto você espera por dados na chamada para await()
.
overview/OverviewViewModel.kt
. Na parte superior do arquivo (após as importações,
antes da definição da classe), adicione um enum
para representar todos os status
disponíveis:enum class MarsApiStatus { LOADING, ERROR, DONE }
_response
em toda a classe
OverviewViewModel
para _status
. Como você adicionou suporte para as
_properties
LiveData
anteriormente neste tutorial, a resposta completa do
serviço da web não foi usada. Você precisa de um LiveData
aqui para controlar o status
atual, então você pode simplesmente renomear as variáveis existentes. Além disso, altere os tipos de String
para MarsApiStatus
.
private val _status = MutableLiveData<MarsApiStatus>()
val status: LiveData<MarsApiStatus>
get() = _status
getMarsRealEstateProperties()
e atualize
_response
para _status
aqui também. Altere a string "Success"
para
o estado MarsApiStatus.DONE
e a string "Failure"
para
MarsApiStatus.ERROR
. MarsApiStatus.LOADING
antes do bloco try {}
. Este é o
status inicial enquanto a co-rotina está em execução e você está esperando pelos dados. O bloco
try / catch {}
completo agora se parece com isto: _status.value = MarsApiStatus.LOADING
try {
_properties.value = MarsApi.retrofitService.getProperties()
_status.value = MarsApiStatus.DONE
} catch (e: Exception) {
_status.value = MarsApiStatus.ERROR
}
catch {}
, defina as _properties
LiveData
para uma lista vazia. Isso limpa o RecyclerView
. } catch (e: Exception) {
_status.value = MarsApiStatus.ERROR
_properties.value = ArrayList()
}
Agora você tem um status no modelo de vista, mas é apenas um conjunto de estados. Como você faz com que ele
apareça no próprio aplicativo? Nesta etapa, você usa um ImageView
, conectado à vinculação de
dados, para exibir ícones para os estados de carregamento e erro. Quando o aplicativo está no estado de
carregamento ou em estado de erro, o ImageView
deve estar visível. Quando o aplicativo é
carregado, o ImageView
deve estar invisível.
BindingAdapters.kt
. Adicione um novo adaptador de vinculação chamado
bindStatus()
que leva um valor ImageView
e MarsApiStatus
como
argumentos. Importe com.example.android.marsrealestate.overview.MarsApiStatus
quando
solicitado.@BindingAdapter("marsApiStatus")
fun bindStatus(statusImageView: ImageView,
status: MarsApiStatus?) {
}
when {}
dentro do método bindStatus()
para alternar entre os
diferentes status. when (status) {
}
when {}
, adicione um caso para o estado de carregamento
(MarsApiStatus.LOADING
). Para este estado, defina ImageView
como visível e
atribua a animação de carregamento. Este é o mesmo drawable de animação que você usou para o Glide na
tarefa anterior. Importe android.view.View
quando solicitado.when (status) {
MarsApiStatus.LOADING -> {
statusImageView.visibility = View.VISIBLE
statusImageView.setImageResource(R.drawable.loading_animation)
}
}
MarsApiStatus.ERROR
. Similarmente ao que você
fez para o estado LOADING
, defina o status ImageView
para visível e reutilize o
drawable de erro de conexão.MarsApiStatus.ERROR -> {
statusImageView.visibility = View.VISIBLE
statusImageView.setImageResource(R.drawable.ic_connection_error)
}
MarsApiStatus.DONE
. Aqui você obteve uma
resposta bem-sucedida, então desligue a visibilidade do status ImageView
para ocultá-lo.
MarsApiStatus.DONE -> {
statusImageView.visibility = View.GONE
}
res/layout/fragment_overview.xml
. Abaixo do elemento RecyclerView
, dentro
do ConstraintLayout
, adicione o ImageView
mostrado abaixo.ImageView
tem as mesmas restrições do RecyclerView
. No entanto, a largura e a
altura usam wrap_content
para centralizar a imagem em vez de esticar a imagem para preencher
a vista. Observe também o atributo app:marsApiStatus
, que faz com que a vista chame seu
BindingAdapter
quando a propriedade de status no modelo de vistas muda.<ImageView
android:id="@+id/status_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:marsApiStatus="@{viewModel.status}" />
Projeto Android Studio: MarsRealEstateGrid
ImageView
para colocar a imagem. Para especificar essas opções, use os métodos
load()
e into()
com Glide.ImageView
. @BindingAdapter
.
apply()
. Por exemplo, use
apply()
com placeholder()
para especificar um drawable de carregamento e use
apply()
com error()
para especificar um drawable de erro. RecyclerView
com um
GridLayoutManager
.RecyclerView
e o layout. Documentação para desenvolvimento em Android:
De outros:
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.
Qual método Glide você usa para indicar o ImageView
que conterá a imagem carregada?
▢ into()
▢ with()
▢ imageview()
▢ apply()
Como você especifica um espaço reservado para imagem para mostrar quando o Glide está carregando?
▢ Use o método into()
com um drawable.
▢ Use RequestOptions()
e chame o método placeholder()
com um drawable.
▢ Atribua a propriedade Glide.placeholder
a um drawable.
▢ Use RequestOptions()
e chame o método loadingImage()
com um drawable.
Como você indica que um método é um adaptador de vinculação?
▢ Chame o método setBindingAdapter()
no LiveData
.
▢ Coloque o método em um arquivo Kotlin chamado BindingAdapters.kt
.
▢ Use o atributo android:adapter
no layout XML.
▢ Anote o método com @BindingAdapter
.
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.