Criar listas dinâmicas com o RecyclerView   Parte do Android Jetpack.

Testar o Compose
O Jetpack Compose é o kit de ferramentas de interface recomendado para Android. Aprenda a trabalhar com layouts no Compose.

O RecyclerView facilita e torna eficiente a exibição de grandes conjuntos de dados. Você fornece os dados e define a aparência de cada item, e a biblioteca RecyclerView, quando necessário, cria os elementos dinamicamente.

O RecyclerView, como o nome indica, recicla esses elementos individuais. Quando um item rola para fora da tela, o RecyclerView não destrói a visualização dele. Em vez disso, o RecyclerView reutiliza a visualização para novos itens que passaram a aparecer na tela. A RecyclerView melhora o desempenho e a capacidade de resposta do app, além de reduzir o consumo de energia.

Classes principais

Várias classes trabalham juntas para criar sua lista dinâmica.

  • RecyclerView é o ViewGroup que contém as visualizações correspondentes aos seus dados. Ela é uma visualização em si, então adicione a RecyclerView ao layout da mesma forma que você adicionaria qualquer outro elemento da IU.

  • Cada elemento individual da lista é definido por um objeto fixador de visualização. Quando o fixador de visualização é criado, ele não tem dados associados a si mesmo. Depois que o fixador de visualização é criado, o RecyclerView vincula-o a seus dados. Para definir o fixador de visualização, estenda RecyclerView.ViewHolder.

  • O RecyclerView solicita visualizações e as vincula aos dados delas, chamando métodos no adaptador. Para definir o adaptador, estenda RecyclerView.Adapter.

  • O gerenciador de layout organiza os elementos individuais na sua lista. Você pode usar um dos gerenciadores de layout fornecidos pela biblioteca RecyclerView ou pode definir seu próprio gerenciador. Todos os gerenciadores de layout são baseados na classe abstrata LayoutManager da biblioteca.

Você pode conferir como todas as peças se encaixam no app de amostra RecyclerView (Kotlin) ou no app de amostra RecyclerView (Java) (links em inglês).

Etapas para implementar o RecyclerView

Se você quiser usar o RecyclerView, é necessário realizar algumas ações. Elas serão explicadas em detalhes nas seções a seguir.

  1. Decida como a lista ou a grade vai ficar. Normalmente, você pode usar um dos gerenciadores de layout padrão da biblioteca RecyclerView.

  2. Crie a aparência e o comportamento de cada elemento da lista. Com base nisso, estenda a classe ViewHolder. A versão do ViewHolder fornece toda a funcionalidade para os itens da lista. O fixador de visualização é um wrapper em torno de uma View, e essa visualização é gerenciada por RecyclerView.

  3. Defina o Adapter que associa seus dados às visualizações ViewHolder.

Há também as opções avançadas de personalização, que permitem adaptar o RecyclerView de acordo com suas necessidades.

Planejar seu layout

Os itens na RecyclerView são organizados por uma classe LayoutManager. A biblioteca RecyclerView fornece três gerenciadores de layout, que processam as situações de layout mais comuns:

  • LinearLayoutManager organiza os itens em uma lista unidimensional.
  • GridLayoutManager organiza os itens em uma grade bidimensional:
    • Se a grade for organizada na vertical, GridLayoutManager tentará fazer com que todos os elementos em cada linha tenham a mesma largura e altura, mas linhas diferentes podem ter alturas diferentes.
    • Se a grade for organizada na horizontal, GridLayoutManager tentará fazer com que todos os elementos em cada coluna tenham a mesma largura e altura, mas colunas diferentes podem ter larguras diferentes.
  • StaggeredGridLayoutManager é semelhante a GridLayoutManager, mas não exige que os itens de uma linha tenham a mesma altura (para grades verticais) ou itens na mesma coluna tenham a mesma largura (para grades horizontais). O resultado é que os itens em uma linha ou coluna podem acabar afastados um do outro.

Você também precisa projetar o layout dos itens individuais. Você vai precisar desse layout ao projetar o fixador de visualização, conforme descrito na próxima seção.

Implementar o adaptador e o fixador de visualização

Depois de determinar seu layout, é necessário implementar o Adapter e o ViewHolder. Essas duas classes trabalham juntas para definir como seus dados são exibidos. O ViewHolder é um wrapper em torno da View que contém o layout de um item individual na lista. O Adapter cria objetos ViewHolder conforme necessário e também define os dados para essas visualizações. O processo de associação de visualizações aos dados é chamado de vinculação.

Ao definir o adaptador, você substitui três métodos principais:

  • onCreateViewHolder(): RecyclerView chama esse método sempre que precisa criar um novo ViewHolder. O método cria e inicializa o ViewHolder e o View associado, mas não preenche o conteúdo da visualização. O ViewHolder ainda não foi vinculado a dados específicos.

  • onBindViewHolder(): RecyclerView chama esse método para associar um ViewHolder aos dados. O método busca os dados apropriados e usa esses dados para preencher o layout do fixador de visualização. Por exemplo, se a RecyclerView mostrar uma lista de nomes, o método poderá encontrar o nome apropriado na lista e preencher o widget TextView do detentor de visualização.

  • getItemCount(): RecyclerView chama esse método para conferir o tamanho do conjunto de dados. Por exemplo, em um app de lista de endereços, pode ser o número total de endereços. O RecyclerView usa essa função para determinar quando não há mais itens a serem exibidos.

Veja um exemplo típico de adaptador simples com um ViewHolder aninhado que exibe uma lista de dados. Nesse caso, o RecyclerView exibe uma lista simples de elementos de texto. O adaptador recebe uma matriz de strings que contém o texto dos elementos ViewHolder.

Kotlin

class CustomAdapter(private val dataSet: Array<String>) :
        RecyclerView.Adapter<CustomAdapter.ViewHolder>() {

    /**
     * Provide a reference to the type of views that you are using
     * (custom ViewHolder)
     */
    class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
        val textView: TextView

        init {
            // Define click listener for the ViewHolder's View
            textView = view.findViewById(R.id.textView)
        }
    }

    // Create new views (invoked by the layout manager)
    override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): ViewHolder {
        // Create a new view, which defines the UI of the list item
        val view = LayoutInflater.from(viewGroup.context)
                .inflate(R.layout.text_row_item, viewGroup, false)

        return ViewHolder(view)
    }

    // Replace the contents of a view (invoked by the layout manager)
    override fun onBindViewHolder(viewHolder: ViewHolder, position: Int) {

        // Get element from your dataset at this position and replace the
        // contents of the view with that element
        viewHolder.textView.text = dataSet[position]
    }

    // Return the size of your dataset (invoked by the layout manager)
    override fun getItemCount() = dataSet.size

}

Java

public class CustomAdapter extends RecyclerView.Adapter<CustomAdapter.ViewHolder> {

    private String[] localDataSet;

    /**
     * Provide a reference to the type of views that you are using
     * (custom ViewHolder)
     */
    public static class ViewHolder extends RecyclerView.ViewHolder {
        private final TextView textView;

        public ViewHolder(View view) {
            super(view);
            // Define click listener for the ViewHolder's View

            textView = (TextView) view.findViewById(R.id.textView);
        }

        public TextView getTextView() {
            return textView;
        }
    }

    /**
     * Initialize the dataset of the Adapter
     *
     * @param dataSet String[] containing the data to populate views to be used
     * by RecyclerView
     */
    public CustomAdapter(String[] dataSet) {
        localDataSet = dataSet;
    }

    // Create new views (invoked by the layout manager)
    @Override
    public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
        // Create a new view, which defines the UI of the list item
        View view = LayoutInflater.from(viewGroup.getContext())
                .inflate(R.layout.text_row_item, viewGroup, false);

        return new ViewHolder(view);
    }

    // Replace the contents of a view (invoked by the layout manager)
    @Override
    public void onBindViewHolder(ViewHolder viewHolder, final int position) {

        // Get element from your dataset at this position and replace the
        // contents of the view with that element
        viewHolder.getTextView().setText(localDataSet[position]);
    }

    // Return the size of your dataset (invoked by the layout manager)
    @Override
    public int getItemCount() {
        return localDataSet.length;
    }
}

O layout de cada item de visualização é definido em um arquivo de layout XML, como de costume. Nesse caso, o app tem um arquivo text_row_item.xml como este:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="@dimen/list_item_height"
    android:layout_marginLeft="@dimen/margin_medium"
    android:layout_marginRight="@dimen/margin_medium"
    android:gravity="center_vertical">

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/element_text"/>
</FrameLayout>

Próximas etapas

O snippet de código abaixo mostra como usar o RecyclerView.

Kotlin

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val dataset = arrayOf("January", "February", "March")
        val customAdapter = CustomAdapter(dataset)

        val recyclerView: RecyclerView = findViewById(R.id.recycler_view)
        recyclerView.layoutManager = LinearLayoutManager(this)
        recyclerView.adapter = customAdapter

    }

}

Java

RecyclerView recyclerView = findViewById(R.id.recycler_view);
recyclerView.layoutManager = new LinearLayoutManager(this)
recyclerView.setAdapter(customAdapter);

A biblioteca também oferece muitas maneiras de personalizar a implementação. Para mais informações, consulte Personalização avançada do RecyclerView.

Outros recursos

Para saber mais sobre testes no Android, consulte os recursos a seguir.

Apps de amostra