Entendendo RecyclerView de Uma Vez Por Todas
Tags: braziliandevs, kotlin, android
Published: 2023-12-04 16:05:38

E aí, cês tão bem?

Nos últimos dias, tenho me dedicado a estudar Android e me deparei com o seguinte desafio: entender o `RecyclerView`.

Então, este artigo é para você que não está entendendo muito bem como isso funciona e eu, como uma boa amante de formas diferentes de explicar coisas complexas, cá estou.

## Usando RecyclerView para organizar uma festa 🥳

Para te ajudar a entender, vou precisar que você comece imaginando que vamos dar uma festa de comidas típicas do meu estado, Minas Gerais, e para isso, precisamos definir algumas coisas. Saiba que o local da festa já foi escolhido.

Precisamos decidir como organizar as mesas e servir os pratos típicos. Para isso, pensei em nos organizarmos da seguinte forma:

- Precisamos definir no espaço principal onde iremos organizar as mesas e cadeiras para nossos convidados. Temos que distribuir tudo perfeitamente para que a festa seja agradável e todos possam aproveitar.
- Temos um cardápio com todos os pratos que queremos servir. Vamos precisar de um chef/assistente para nos ajudar a decidir quais pratos do cardápio incluir na festa e também ajudar a organizá-los nos suportes adequados. Se decidirmos adicionar um novo prato ao cardápio, nosso Chef nos ajuda a garantir que tenhamos um suporte certo para esse prato. Ele vai gerenciar essa relação entre o cardápio e os suportes, facilitando a escolha e exibição dos pratos na festa.
- Agora, pense nos pratos típicos que queremos servir. Vamos precisar de um suporte para cada prato. Cada suporte será designado para segurar um prato específico, garantindo que quando decidirmos servir algo, já temos um lugar definido para isso. Sem o suporte, teríamos que procurar constantemente onde colocar ou onde está cada prato na mesa, e isso deixaria o atendimento aos convidados menos fluído.
- Pensar na disposição das mesas. Precisamos contratar um planejador de festas. Ele vai nos ajudar a decidir se queremos organizar as mesas em fileiras, círculos ou qualquer outra forma que torne a festa mais aconchegante. Se decidirmos que queremos mesas em círculo, o planejador organiza automaticamente as mesas dessa forma. Ele ajuda a criar o layout ideal para que todos os convidados possam aproveitar a festa da melhor maneira possível.

Resumindo, temos que:

- Definir o espaço principal da festa;
- Suporte especial para cada prato;
- Assistente que organiza o cardápio nos suportes;
- Planejador que decide como organizar as mesas.

E agora você deve estar pensando, mas o que isso tem a ver com RecyclerView?

Festas e RecyclerView, acredito eu, que não tenham muitas coisas em comum. Ouso dizer que são até opostos demais 😅, mas vamos entender um pouco mais onde quero chegar com essa comparação:

O `RecyclerView` será o nosso espaço principal da festa, o `ViewHolder` é o suporte especial para cada prato, o `Adapter` é o assistente que organiza o cardápio nos suportes, e o `LayoutManager` é o planejador que decide como organizar as mesas. Juntos, eles tornam a festa organizada e garantem que todos desfrutem da experiência.

Agora que entendemos um pouco mais sobre o que é o que, vamos para o código!

## Código e um pouco de teoria 💻	

O RecyclerView é tipo um mestre da reciclagem na tela do seu app. Sabe quando você olha para uma lista enorme no celular e pensa "poxa, será que precisava carregar tudo de uma vez?" - é aí que o RecyclerView entra.

Imagina que você está criando uma lista que não para de crescer, tipo uma lista de mensagens de chat. O RecyclerView é como o chefão dessa operação. Ele garante que só os itens que estão aparecendo na tela sejam criados, economizando bateria e tornando tudo mais rápido.

A equipe do RecyclerView inclui alguns membros importantes como já falamos anteriormente:

- RecyclerView: Funciona como o componente visual responsável por posicionar e exibir a lista na tela.
- ViewHolder: Serve como a referência para cada item presente na lista, desempenhando um papel crucial na reciclagem de componentes.
- Adapter: Responsável por mapear os dados do modelo para cada item exibido na lista, garantindo uma conexão eficiente entre os dados e a interface.
- LayoutManager: É o componente encarregado de gerenciar a disposição dos elementos na RecyclerView, proporcionando controle sobre o layout da lista.

Começamos criando nosso espaço principal, ou seja, o `RecyclerView`. Podemos adicioná-lo diretamente no XML ou pelo editor de layout:

```XML
<androidx.recyclerview.widget.RecyclerView  
    android:id="@+id/recyclerView"  
    android:layout_width="match_parent"  
    android:layout_height="match_parent" />

```

Agora podemos buscá-lo no nosso código Kotlin:


```kotlin
val recyclerView: RecyclerView = findViewById(R.id.recyclerView)

```

**E já ta pronto? Ainda não!** 

Primeiro vamos precisar vincular nosso `RecyclerView` a um `LayoutManager`, e depois:

1. Vamos precisar de um conjunto de dados, depois precisamos;
2. Vincular o conjunto de dados a uma representação visual com o `ViewHolder` e, por fim;. 
3. Vincular este dados ao `RecyclerView` utilizando um `Adapter`;


O LayoutManager é o cara responsável por organizar os itens visuais dentro do nosso `RecyclerView`, definindo também o critério de quando os itens devem ser "reciclados".

Para começar vamos usar o `LinearLayoutManager`, para listas verticais e simples.

```kotlin
recyclerView.layoutManager = LinearLayoutManager(this)
```

Agora, vamos focar nos itens da nossa lista!

Vou criar um conjunto de dados de comidas. Então, primeiro, criamos a classe `Food`. Lembrando que esta classe será um modelo de dados e para isso precisamos criá-la como uma data class.

```kotlin
data class Food(val name: String, val chef: String)
```

Depois temos que criar uma lista usando nosso modelo:

```kotlin
val FoodList = listOf(  
    Food("Feijão tropeiro", "Ana Laura"),  
    Food("Frango caipira", "Julio"),  
    Food("Pamonha", "Gabriel"),  
)
```

Agora, vamos para a parte de vincular o conjunto de dados a uma representação visual com o ViewHolder.

Os `ViewHolders` atuam como um cache para elementos visuais, armazenando referências às `views` no layout para otimizar a atualização da interface gráfica. _(Lembre-se que estamos falando de dispositivos móveis, ou seja a capacidade é muito menor que de um computador)_

São elementos que serão exibidos, exigindo a criação de uma classe `ViewHolder` que estende `RecyclerView.ViewHolder`. Esta classe recebe um parâmetro por padrão que é o `itemView` e também deve ter um método "bind", responsável por vincular dados, associando elementos visuais aos itens do conjunto de dados.

```kotlin
class FoodViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {  
    fun bind(food: Food) {  
        itemView.findViewById<TextView>(R.id.foodName).text = food.name  
        itemView.findViewById<TextView>(R.id.foodChef).text = food.chef  
    }  
}
```

_Ah, perceba que ali a gente já selecionou esses dois ID's `foodName` e `foodChef`, mas ainda não os criamos no nosso XML. Vamos conversar sobre isso:_

Agora, o que precisamos fazer é criar o layout do nosso `ViewHolder`, ou seja, qual será o layout de cada item do nosso `RecyclerView`. 

Este layout é criado da mesma forma que criamos qualquer outra `Activity`, criando um xml de layout com o nome de `food_item.xml`.

```XML
<?xml version="1.0" encoding="utf-8"?>  
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    android:layout_width="match_parent"  
    android:layout_height="wrap_content"  
    android:orientation="vertical"  
    android:padding="10dp">  
  
    <TextView        android:id="@+id/foodName"  
        android:layout_width="match_parent"  
        android:layout_height="wrap_content"  
        android:textSize="20sp"  
        android:textStyle="bold" />  
  
    <TextView        android:id="@+id/foodChef"  
        android:layout_width="match_parent"  
        android:layout_height="wrap_content"  
        android:textSize="15sp" />  
</LinearLayout>

```


Agora que estabelecemos nosso `ViewHolder`, avançamos para a construção do `Adapter`. Nesse processo, vamos sobrescrever os métodos necessários para associar os dados do tipo `Food` ao nosso layout. 

Imagine o `Adapter` como um intermediário que conecta nossos dados de comida ao layout. 

Para começar, criamos a classe `FoodAdapter`, que recebe uma lista de objetos `Food` e estende a classe `RecyclerView.Adapter<FoodViewHolder>`.

Esta classe é como um organizador que recebe uma lista de comidas, que chamamos de "conjunto de dados", e ela é especializada para trabalhar com o nosso `ViewHolder` de comidas, o `FoodViewHolder`. É basicamente uma maneira de dizer ao sistema como os dados (comidas) devem ser exibidos no layout.

```kotlin
class FoodAdapter(private val foods: List<Food>) : RecyclerView.Adapter<FoodViewHolder>() {

}
```

Antes da gente continuar, preciso te explicar o que é o `onCreateViewHolder()`: Este método é acionado durante a criação do `ViewHolder` e é responsável por gerar os elementos visuais para cada item da lista. 

O termo utilizado para descrever esse processo é "Inflate". 
_Em outras palavras, o método realiza a criação visual de cada elemento da lista, preparando-os para serem exibidos no `RecyclerView`_

```kotlin
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FoodViewHolder { 
	/*estamos criando um Inflater, e gerando um inflate, que é o método que cria os elementos, tendo como primeiro parâmetro o layout do elemento que deve ser replicado. Em nosso caso, o food_item */*
    val view = LayoutInflater.from(parent.context).inflate(R.layout.food_item, parent, false)  
    return FoodViewHolder(view)  
}
```

👀_ps: isso será um método da classe `FoodAdapter`_

Agora, precisamos sobrescrever o método de vínculo `onBindViewHolder()`. Ele recebe como parâmetro o nosso `ViewHolder` de comidas e chama o nosso método `bind()` para cada um de nossos elementos de lista. O método `bind` é uma convenção usada para associar os dados de um item específico do conjunto de dados ao `ViewHolder` correspondente.


```kotlin
override fun onBindViewHolder(holder: FoodViewHolder, position: Int) {  
    
    val food = foods[position]  
    
    holder.bind(food)  
}
```

👀_ps: Lembra que lá na nossa classe `FoodViewHolder` tem um método bind, o que será que ele faz mesmo? xD_

A classe `FoodAdapter` herda de `RecyclerView.Adapter` e implementa alguns métodos abstratos necessários, como `getItemCount()` que retorna a quantidade de itens.

```kotlin
override fun getItemCount(): Int {  
    return foods.size  
}
```

Agora que já fizemos tudo isso, podemos vincular o `Adapter` ao `RecyclerView` que criamos lá atrás:

```kotlin
// essa variável aqui foi criada lá atrás
val recyclerView: RecyclerView = findViewById(R.id.recyclerView)

//criando o Adapter a partir da nossa lista de comidas
val adapter = FoodAdapter(foodList)

//vinculando o adapter ao RecyclerView
recyclerView.adapter = adapter

```

E fim, temos uma lista criada 🥰


Eu criei um [repositório no github](https://github.com/anabergerr/foodlist-example) com o código e _~~com um desenho não muito bom~~_ que eu fiz pra ajudar entender. 


Se você leu até o final reage com um 💟 se não, não precisa reagir :(.


`bjs bjs e até a próxima`