Criando uma lista com ListView no Android

Estou desenvolvendo um app para cadastrar todos os cursos do Alura que eu fiz ou estou fazendo, para que eu possa verificar quais são os cursos que eu já terminei ou se ainda precisa finalizar. Então inicialmente eu criei uma classe para representar meus cursos:

public class Curso {

    private String nome;
    private String descricao;
    private EstadoAtual estado;

    //métodos

}

E um ENUM pra representar o estado atual do curso, ou seja, se ele está finalizado ou se está sendo feito:

public enum EstadoAtual {

    FAZENDO{
        @Override
        public String toString() {
            return "Fazendo";
        }
    }, FINALIZADO{
        @Override
        public String toString() {
            return "finalizado";
        }
    };
}

http://blog.alura.com.br/wp-admin/edit.php

Como fazemos para criar a nossa tela? Precisamos criar um XML para representá-la, certo? Então vamos criar esse XML na pasta res/layout com o nome activity_lista_de_cursos.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ListView
        android:id="@+id/lista"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

    </ListView>

</RelativeLayout>

Muito bom, temos o nosso layout, porém precisamos associar esse layout a uma activity, como podemos fazer isso? Bom, primeiro nós precisamos de uma activity, então vamos criar a ListaDeCursosActivity que estende a classe Activity ou uma de suas filhas, nesse caso, usarei a classe AppCompatActivity por questão de compatibilidade:

public class ListaDeCursosActivity extends AppCompatActivity {

}

Agora que temos a nossa activity, podemos implementar o método onCreate() que irá settar o nosso layout e vai pegar a referência da ListView:

public class ListaDeCursosActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_lista_de_cursos);

        ListView listaDeCursos = (ListView) findViewById(R.id.lista);   

    }

}

Settamos o nosso layout e pegamos a referência para a nossa ListView e agora nós precisamos pegar a nossa lista de cursos:

@Override
protected void onCreate(Bundle savedInstanceState) {

    List<Curso> cursos = todosOsCursos();

    ListView listaDeCursos = (ListView) findViewById(R.id.lista);

    //métodos

}

Temos a nossa List e a nossa ListView, porém, não existe um método da classe ListView capaz de adicionar uma List, uma pena… E agora? O que podemos fazer? No Android, existe um especialista em lidar com listas chamado adapter e, para nossa felicidade, a ListView consegue adicionar esse adapter! E como podemos criar um adapter? Por meio da classe ArrayAdapter:

@Override
protected void onCreate(Bundle savedInstanceState) {
        
    //métodos

    ArrayAdapter<Curso> adapter = new ArrayAdapter<Curso>();

}

Ops, há um detalhe na instância do ArrayAdapter, todos os construtores dele exigem pelo menos um Context que será a nossa activity e um int que será o recurso que representará cada item da lista, o Android disponibiliza para nós alguns recursos para utilizarmos, nesse caso, utilizaremos o recurso android.R.layout.simple_list_item_1 que é uma representação bem básica para cada item da lista:

@Override
protected void onCreate(Bundle savedInstanceState) {
    
    //métodos

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

}

Certo, instanciamos o nosso ArrayAdapter só que ainda não informamos em momento algum que queremos que ele adapte a nossa lista de cursos! Como podemos passar a nossa lista para ele? O ArrayAdapter possui diversos construtores e, para a nossa alegria, um deles recebe uma List que é justamente o que precisamos:

@Override
protected void onCreate(Bundle savedInstanceState) {

    //métodos

    List<Curso> cursos = todosOsCursos();

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

}

Certo, criamos nosso adapter, o que precisamos fazer agora? De alguma forma, nós precisamos fazer com o que a nossa ListView utilize esse adapter, mas como podemos fazer isso? Sabemos que a classse ListView não é capaz de adicionar uma List, porém ela pode settar um adapter por meio do método setAdapter():

public class ListaDeCursosActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_lista_de_cursos);

        List<Curso> cursos = todosOsCursos();

        ListView listaDeCursos = (ListView) findViewById(R.id.lista);

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

        listaDeCursos.setAdapter(adapter);

    }

    //métodos

}

Vamos testar a nossa app:

tela-lista-com-hashcode

Opa! Calma aí! Hashcode da classe? Não era bem isso que eu queria… O que será que aconteceu? Quando um adapter recebe uma List, ele imprime exatamente o conteúdo de cada posição da List, por exemplo, se for uma lista de String imprime a String de cada posição, se for de int imprime int e por aí vai, porém no nosso caso, é uma lista de Curso, ou seja, ele chamou o toString de cada curso dentro da lista e por isso apareceu o hashcode de cada um… Que tal personalizarmos o toString()? Vamos então implementar o nosso toString() para que seja impresso as informações de um curso:

public class Curso {

    private String nome;
    private String descricao;
    private EstadoAtual estado;
    
    //métodos

    @Override
    public String toString() {
        return "Curso: " + nome + " Descrição: " + 
        descricao + " Estado: " + estado;
    }
}

Agora se testamos a nossa app novamente:

tela-lista-com-cursos

Maravilha! Agora sim a nossa lista mostra as informações de cada curso da lista!

Vimos que, para criarmos uma lista no android nós precisamos definir uma ListView no nosso XML que representará a nossa tela e referenciá-la na nossa activity. Além disso, vimos que apenas a ListView não é o suficiente para que possamos adicionarmos a nossa List e por isso precisamos de um adapter que é especialista em lidar com List e informar para a ListView quais serão os valores de cada item da lista. Vimos também que, quando passamos uma lista de objetos nossos, como por exemplo a classe Curso, por padrão será impresso o próprio objeto, ou seja, o toString() padrão e, se quisermos uma informação diferente, precisamos implementá-lo de acordo com a nossa necessidade.

E aí, gostou de criar uma lista no Android? Quer aprender mais sobre Android? Que tal dar uma olhada nos cursos de mobile? Com cursos focados em Android e desenvolvimento mobile para que você crie sua primeira app e desenvolva mais o seu conhecimento!


Content Editor at Alura and Software Developer

  • Fábio da Silva Santana

    Legal. Já pensou em usar um recyclerView no lugar da listView. Segundo a documentação da google o RecyclerView é uma evolução do ListView, que ganha em flexibilidade e desemepenho.

    • Sim Fábio, eu pretendo escrever futuramente sobre ele. Eu não escrevi sobre o RecyclerView nesse post, pois a implementação do ListView é mais fácil e não exige muitos detalhes para quem está começando! Mas Obrigado pelo comentário. 🙂

  • Pingback: Blog do Alura – Personalizando uma ListView no Android()

  • Guilherme

    O método todosOsCursos()., está sendo declarado aonde ?

    • Alex Felipe

      Oi Guilherme, tudo bem? Boa observação! Esse método não foi declarado justamente para manter mais o foco no conteúdo de Android. Mas entenda esse método como um acesso aos dados qualquer, ou seja, poderia ser um acesso ao SQLite ou um método que realiza uma requisição para um servidor e devolve uma lista de cursos.

      • Guilherme

        Oi alex, tudo e com você? Entendi, muito obrigado cara! O material ficou muito bom, Parabéns!

        • Alex Felipe

          Tudo sim Guilherme! Muito obrigado pelo feedback 🙂

  • Pingback: Blog da Alura: desenvolvimento, design e muita tecnologia – Utilizando o padrão ViewHolder()

Próximo ArtigoDepoimento do aluno: Matheus Henrique