Você sabe quando e porque utilizar as ListViews no seu aplicativo Android?

Muita gente utiliza esse recurso, mas nem imagina o porque esses componentes são tão importantes. As ListViews são muito mais do que simples listagens em aplicativos Android, elas fazem parte da arquitetura e de boas práticas de desenvolvimento Android.

Existem vários tipos de ListViews, cada uma serve para uma situação diferente e para resolver problemas diversos em seus aplicativos.

Então, continue lendo este artigo para descobrir quais os tipos de ListViews e o verdadeiro motivo para usa-las:

A Memória é um Recurso Limitado

Muitos dos recursos que temos na vida, como tempo e dinheiro, são limitados. Assim, temos de ser eficientes quando decidimos usá-los.

Da mesma forma, a memória humana também é um recurso limitado e temos um limite para lembrar de nomes, numeros e etc.

Isso se aplica também a nossos dispositivos celulares e tablets, que tem memória fixa e extremamente limitada se formos comparar com um laptop ou  um desktop.

A memória do nosso dispositivo móvel é usada para armazenar todos os tipos de coisas, como músicas, mensagens de texto, fotos e muito mais. Além de compartilhar com o sistema operacional Android e com todos os outros aplicativos que usamos, incluindo o nosso aplicativo também.

Imagine se um desses aplicativos acabar consumindo muita memória do dispositivo. Isso pode ter um impacto significativo na execução de todos os outros aplicativos.

E o pior de tudo, isso geraria um efeito negativo na usabilidade geral de todo o dispositivo, o que pode levar a uma experiência muito frustrante para o usuário.

Mas onde eu quero chegar com tudo isso? Nós como desenvolvedores Android, devemos ter em mente que a memória é um recurso limitado, e precisamos criar aplicativos que usem essa memória de forma eficiente.

Problema

Um aplicativo de contatos contém 1.000 nomes e números armazenados na sua lista de contatos.

Imagine que o desenvolvedor desse aplicativo utilizou um LinearLayout com TextView para montar essa lista de 1.000 contatos na tela do usuário.

Isso iria gastar muita memória para armazenar e exibir as 1.000 TextViews, mesmo que nem todos os 1.000 contatos estejam sendo mostrados na tela ao mesmo tempo.

Se uma grande parte da memória está criando e armazenando esses contatos, então não sobrou muito espaço para executar outras coisas no telefone. E isso pode causar a parada de outros aplicativos ou nem mesmo conseguir executar-los.

Solução

Nós desenvolvedores Android temos que tomar cuidado referente ao uso de recursos de memória. Nosso aplicativo tem que funcionar muito bem com sem interferir em outros aplicativos do dispositivo.

Em nosso aplicativo de contatos os usuários só vêem cinco contatos na tela por vez. Portanto, não há necessidade de criar todos os 1.000 TextViews e ocupar memória de forma desnecessária.

Assim, para resolver este problema, poderíamos reutilizar as Views, pois há apenas cinco que aparecem na tela naquele momento. Esta estratégia é chamada de Reciclagem de Views.

Reciclagem de Views

A estratégia de Reciclagem de Views ajuda a exibir listas longas dentro dos aplicativos reutilizando as Views que não estão visíveis na tela naquele momento.

Quando falamos em Views, tenha em mente todo o layout para uma única linha da lista. O layout para uma única linha é provavelmente composto por várias Views dentro de ViewGroups.

Nós precisamos criar apenas as Views suficientes dos itens que serão mostrados e irão preencher a tela do usuário. Isso significa que se rolarmos a lista para cima, não precisamos mais ver as Views antigas.

Isso significa que se uma View não está mais visível na tela, podemos reutilizá-lo alterando apenas os dados, como textos e imagens. Assim não precisamos perder tempo criando a View do zero novamente.

Todas as Views que não estão sendo utilizadas mais, são colocadas em uma “pilha de sucata” para serem recicladas e reutilizadas mais tarde.

Por exemplo, se um usuário rolar a tela para ver os outros itens da lista, o ListView percebe que precisa criar mais linhas da lista. Assim, quando o usuário rolar a tela, parece que os itens da lista estavam lá o tempo todo.

Em vez de criar um novo Item da lista do zero, uma View antiga é reutilizada, criando mais linhas sob demanda reciclando as Views.

O objetivo de tudo isso é criar o mínimo de itens de lista possível, pois é muito caro inflar os XML de layouts para objetos Java.

Para utilizar essa estratégia e exibir listas de maneira eficiente, utilizamos algum tipo de ListView juntamente com um Adapter.

O que é Adapter

Antes de entrarmos definitivamente no assunto das LisViews, precisamos entender o que são e como funcionam os Adapters dentro de todo esse conceito que vimos até agora.

Adapter é responsável por gerenciar e adaptar os dados nas Views, ou, no layout da linha do item. Além de ser responsável por criar uma View para cada item do conjunto de dados.

Um exemplo de layout muito utilizado em uma lista, tem uma imagem no lado esquerdo e duas linhas de texto no meio, conforme a imagem a seguir.

O Adapter infla o layout de cada linha em seu método getView() e atribuir os dados para as Views individuais.

Os Adapters não são usados apenas pelas ListViews, mas também por outros componentes que estendem o AdapterView como, por exemplo, Spinner e StackView.

O Android fornece algumas implementações de Adapters prontas para serem usadas. Os mais importantes são: SimpleCursorAdapterArrayAdapter e CursorAdapter.

O ArrayAdapter pode manipular dados com base em Arrays ou java.util.List. Já o SimpleCursorAdapter e CursorAdapter podem manipular dados vindos do banco de dados do Android, o SQLite.

Existem dois métodos importantes nos Adapters para fazer a atualização dos dados e avisar as ListViews que algo mudou:

  • notifyDataSetChanged(): É chamado se os dados tiverem sido alterados ou se houver novos dados disponíveis.
  • notifyDataSetInvalidated(): É chamado se os dados não estiverem mais disponíveis.

Para tudo isso funcionar, o Adapter é atribuído ao ListView através do método setAdapter().

Os 2 Tipos Simples de ListViews

Existem 2 tipos de ListViews simples que são mais utilizados pelos desenvolvedores no desenvolvimento Android.

A primeira é a classe ListView, que exibe uma lista vertical rolável de itens. A segunda, é a classe GridView, que organiza os itens de forma vertical, rolável e também separa em colunas como se fosse uma galeria.

A utilização de cada umas dessas 2 classes varia de acordo com a sua necessidade em mostrar os dados para o usuário.

Vamos ver mais em detalhes cada uma delas.

ListView

A ListView é um dos componentes mais utilizados para listar dados na plataforma Android de forma eficiente. Basicamente ela organiza os dados um seguido do outro em formato vertical com a opção de rolagem.

Para utilizar a ListView, primeiro precisamos adicionar o componente em nosso XML de layout conforme o exemplo.

<ListView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/listview"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" />

Depois em nossa Activity, no método onCreate(), nós recuperamos o componente pelo ID para utiliza-lo mais tarde.

ListView listview = (ListView) findViewById(R.id.listview);

Agora precisamos criar nossos dados. Vamos utilizar uma Array de Strings com os nomes das versões do Android como exemplo.

String[] dados = new String[] { "Cupcake", "Donut", "Eclair", "Froyo", "Gingerbread", 
                                "Honeycomb", "Ice Cream Sandwich", "Jelly Bean",
                                "KitKat", "Lollipop", "Marshmallow", "Nougat" };

Vamos instanciar a classe ArrayAdapter tipando ela com dados do tipo String. No construtor da classe vamos passar os seguintes parâmetros de forma sequencial: Context, ID do layout e a Array de dados.

ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, dados);

Nesse caso, estamos utilizando o layout android.R.layout.simple_list_item_1 padrão para a linha da ListView.

Depois adicionamos o Adapter dentro da nossa ListView utilizando o método setAdapter().

listview.setAdapter(adapter);

E é só isso, nossa implementação está pronta.

GridView

A GridView é muito parecida com a LisView, a não ser por algumas configurações a mais referente as colunas de apresentação dos dados.

Podemos definir o número de colunas utilizando o atributo numColumns e o tamanho das colunas com o atributo columnWidth.

Veja o exemplo de configuração do XML do componente GridView.

<?xml version="1.0" encoding="utf-8"?>
<GridView xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:tools="http://schemas.android.com/tools"
   android:id="@+id/grid"
   android:columnWidth="90dp"
   android:numColumns="2"
   android:layout_width="match_parent"
   android:layout_height="match_parent" />

O restante da implementação pode ser feita exatamente como mostrado para a ListView.

Selecionando um Item da Lista

Para os dois tipos de ListViews mostrados anteriormente, é possivel capturar o clique nos itens das listas.

Para isso, devemos implementar e adicionar a ListView e/ou GridView um OnItemClickListener utilizando o método setOnItemClickListener().

listView.setOnItemClickListener(new OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view,
                int position, long id) {
                Toast.makeText(getApplicationContext(),
                        "Clicou no item " + position, Toast.LENGTH_LONG).show();
        }
});

Modernização com RecyclerView e CardView

Se você modernizar seu aplicativo, a versão Lollipop do Android trouxe dois novos componentes para facilitar a sua vida, RecyclerView e CardView. Dessa forma é muito fácil dar à seu aplicativo uma aparência que esteja em conformidade com as diretrizes do Material Design do Google.

A RecyclerView é uma versão modernizada das classes ListView e GridView fornecidas pela plataforma Android.

Ele resolve vários problemas que as ListVIews existentes têm hoje e foi criado focando em melhorar o desempenho das listas. Também é possível configurar animações para remover e adicionar elementos.

Já o CardView ajuda a criar os itens das listas permitindo que você exiba informações no formato de cartões. Ele pode ter sombras e bordas arredondadas.

Exemplo

Vamos ver um passo a passo simplificado em como implementar uma RecyclerView com CardView.

Instalação da Biblioteca

Como nem todos os dispositivos Android utilizam a versão Lollipop ou superior do Android, precisamos configurar uma biblioteca de suporte para trazer esses recursos as versões mais antigas do Android.

Adicione as seguintes linhas à seção de dependências no arquivo build.grade do seu projeto:

 

compile 'com.android.support:cardview-v7:21.0.+'
compile 'com.android.support:recyclerview-v7:21.0.+'

Caso não tenha familiaridade com esse tipo configuração, veja aqui sobre o Gradle.

Definindo o Item da Lista

Para criar o item da lista, precisamos de um layout XML e uma classe Java que vai carregar os dados que queremos. Para esse exmplo, vamos modelar o item Pessoa.

class Pessoa {
    private String nome;
    private String idade;
    private int fotoId;
 
    Pesoa(String nome, String idade, int fotoId) {
        this.nome = nome;
        this.idade = idade;
        this.fotoId = fotoId;
    } 
   // Implemente os Getters e Setters
}

Agora, vamos criar o layout do item da nossa lista utilizando o CardView. Para isso, vamos precisar criar um arquivo XML chamado item.xml.

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="16dp">
 
    <android.support.v7.widget.CardView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/cv">
 
        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:padding="16dp">
 
            <ImageView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:id="@+id/person_photo"
                android:layout_alignParentLeft="true"
                android:layout_alignParentTop="true"
                android:layout_marginRight="16dp" />
 
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:id="@+id/person_name"
                android:layout_toRightOf="@+id/person_photo"
                android:layout_alignParentTop="true"
                android:textSize="30sp" />
 
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:id="@+id/person_age"
                android:layout_toRightOf="@+id/person_photo"
                android:layout_below="@+id/person_name" />
 
        </RelativeLayout>
    </android.support.v7.widget.CardView>
</LinearLayout>

Criando o Layout com RecyclerView

Dentro do arquivo XML de layout da sua Activity, adicione um RecyclerView:

<android.support.v7.widget.RecyclerView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/rv" />

Depois, no método onCreate() da sua Activity, recupere o componente e adicione um LayoutManager a ele.

Diferente da LisView, o RecyclerView precisa de um LayoutManager para posicionar os itens na lista.

RecyclerView rv = (RecyclerView)findViewById(R.id.rv);
rv.setLayoutManager(new LinearLayoutManager(this));

Existem 3 tipos de layouts pré-definidos: LinearLayoutManager, GridLayoutManager e StaggeredGridLayoutManager.

Criando o Adapter do RecyclerView

Aqui precisamos criar o Adapter que irá preencher os dados no RecyclerView. No entanto, o RecyclerView requer a existência de um objeto RecyclerView.ViewHolder que descreve e fornece acesso a todas as Views dentro de cada linha do item.

public class PessoaAdapter extends RecyclerView.Adapter<PessoaAdapter.PessoaViewHolder>{
 
    public static class PessoaViewHolder extends RecyclerView.ViewHolder {      
        TextView nomeView;
        TextView idadeView;
        ImageView fotoView;
 
        PessoaViewHolder(View itemView) {
            super(itemView);
            nomeView = (TextView)itemView.findViewById(R.id.person_name);
            idadeView = (TextView)itemView.findViewById(R.id.person_age);
            fotoView = (ImageView)itemView.findViewById(R.id.person_photo);
        }
    }
}

Adicione um construtor ao Adapter que recebe uma lista da classe Pessoa e guarde em um atributo de classe.

List<Pessoa> pessoas;
 
PessoaAdapter(List<Pessoa> pessoas){
    this.pessoas = pessoas;
}

Cada Adapter tem três métodos principais: onCreateViewHolder para inflar o layout do item, onBindViewHolder para definir os atributos de exibição com base nos dados e getItemCount para determinar o número de itens.

Precisamos implementar todos os três em nosso Adapter:

@Override
public PessoaViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item, parent, false);
    PessoaViewHolder pvh = new PessoaViewHolder(v);
    return pvh;
}

@Override
public void onBindViewHolder(PessoaViewHolder viewHolder, int i) {
    viewHolder.nomeVIew.setText(persons.get(i).name);
    viewHolder.idadeView.setText(persons.get(i).age);
    viewHolder.fotoView.setImageResource(persons.get(i).photoId);
}

@Override
public int getItemCount() {
    return pessoas.size();
}

Agora no método onCreate() da sua Activity, crie o PessoaAdapter passando uma lista de dados de pessoas e atribua ao RecyclerView.

PessoaAdapter adapter = new PessoaAdapter(pessoasList);
rv.setAdapter(adapter);

Gostou do conteúdo sobre as ListViews?

Esse é só um tópico muito importante do elemento Interface Gráfica. Se quiser saber mais sobre esse e os outros elementos, inscreva-se e assista a nossa AULA GRATUITA: DESCUBRA OS 4 ELEMENTOS OBRIGATÓRIOS PARA VOCÊ SE TORNAR UM DESENVOLVEDOR ANDROID PROFISSIONAL E INDEPENDENTE…MESMO QUE VOCÊ NÃO SEJA UM GÊNIO DA PROGRAMAÇÃO.

Lembre-se de compartilhar esse artigo com seus amigos e qualquer dúvida deixe nos comentários aqui em baixo.

Leia também


Fillipe Cordeiro
Fillipe Cordeiro

Engenheiro da computação e desenvolvedor de software a quase 10 anos, com experiência em tecnologias como Java, Python e Android. Agora, quero te ajudar a mergulhar no universo do Desenvolvimento Android.