›Series summary
- 1. O que acontece quando você usa um ListView?
- 2. O que é um Sliver, afinal?
- 3. Quem realmente controla os Slivers?
- 4. Construindo uma tela inteira usando apenas Slivers
- 5. Criando seu próprio Sliver

O que acontece quando você usa um ListView?
Antes de entender Slivers, precisamos entender por que eles existem.
Índice
O que realmente acontece quando você usa um ListView?
Você provavelmente já escreveu algo assim centenas de vezes:
ListView.builder(
itemCount: products.length,
itemBuilder: (context, index) {
return ProductTile(products[index]);
},
)
Funciona. É rápido! Consegue exibir milhares de itens.
Mas… como isso realmente acontece?
Como o Flutter consegue renderizar uma lista enorme sem travar o aplicativo? Ele cria todos os widgets de uma vez? Como ele sabe quais itens precisam existir? O que acontece quando você faz scroll?
Essas perguntas levam a um dos assuntos mais importantes da arquitetura do Flutter: o sistema de Slivers.
Mas antes de falar sobre Slivers, precisamos entender o caminho que o Flutter percorre quando encontra um simples ListView.
Tudo começa com uma árvore de Widgets
Toda interface Flutter é uma árvore de Widgets.
Imagine algo simples:
Scaffold
└── ListView
├── ProductTile
├── ProductTile
├── ProductTile
└── ...
Essa árvore, porém, não é o que será desenhado na tela. Ela é apenas uma descrição da interface.
Widgets são extremamente leves.
Eles apenas dizem:
Gostaria que existisse uma lista.
Quem realmente constrói a interface são outras camadas do framework.
Durante o processo de construção, o Flutter transforma essa árvore em outra estrutura composta por Elements e, posteriormente, por RenderObjects.
O fluxo simplificado fica assim:
Widgets
↓
Elements
↓
RenderObjects
↓
Pixels na tela
Cada camada possui uma responsabilidade diferente.
- Widget → configuração.
- Element → gerencia o ciclo de vida.
- RenderObject → calcula layout e desenha.
É nessa última camada que a mágica do ListView acontece.
O verdadeiro trabalho do ListView
À primeira vista, o ListView parece um widget especial.
Na prática, ele possui uma responsabilidade muito simples:
Crie uma lista rolável.
Quem faz o trabalho pesado não é o ListView.
Ele apenas configura toda a infraestrutura necessária para que a lista funcione.
Quando usamos:
ListView.builder(...)
estamos dizendo algo como:
Construa apenas os itens necessários conforme o usuário vai rolando.
Perceba que isso é muito diferente de dizer:
Crie todos os widgets agora.
Essa diferença é justamente o motivo pelo qual conseguimos trabalhar com listas enormes.
O processo de layout
Depois da fase de construção da árvore, começa uma das etapas mais importantes do Flutter: o layout.
Todo RenderObject recebe restrições do seu pai.
Esse processo segue sempre a mesma regra:
O pai impõe restrições.
O filho escolhe um tamanho dentro dessas restrições.
O pai posiciona o filho.
É um fluxo extremamente previsível.
No caso de uma lista vertical, o Flutter sabe que:
- a largura geralmente será a largura disponível;
- a altura poderá crescer indefinidamente conforme o conteúdo.
Mas existe um detalhe importante.
Mesmo que existam 20.000 itens na lista… a tela continua tendo apenas alguns centenas de pixels de altura.
Então surge uma pergunta interessante:
Por que calcular o layout de todos os itens se apenas alguns serão visíveis?
A resposta é: ele simplesmente não calcula.
O segredo da performance
Imagine uma lista com 100.000 produtos.
Se cada item tivesse apenas 60 pixels de altura, precisaríamos de milhões de pixels para desenhar toda a lista.
Seria impossível.
Em vez disso, o Flutter faz uma pergunta muito mais inteligente:
Quais itens realmente aparecem dentro da janela visível?
Suponha uma tela com aproximadamente 800 pixels de altura.
Se cada item mede 80 pixels…
Apenas cerca de 10 itens estarão visíveis.
Talvez mais dois ou três acima e abaixo para evitar pequenos atrasos durante o scroll.
Então, naquele momento, o Flutter talvez mantenha apenas 15 RenderObjects vivos.
Não importa se existem:
- 500 itens;
- 5.000 itens;
- 500.000 itens.
O número de objetos realmente ativos continua relativamente pequeno.
Essa é uma das razões pelas quais o Flutter consegue oferecer uma rolagem extremamente fluida.
O que significa “Lazy Loading” aqui?
Muita gente ouve o termo lazy loading e pensa imediatamente em download sob demanda.
No contexto do Flutter, o conceito é diferente.
Aqui significa:
só construir aquilo que realmente será necessário.
Quando um item entra na área visível:
- O widget é criado;
- Seu Element é montado;
- Seu RenderObject participa do layout.
Quando ele sai muito para fora da tela, esses objetos podem ser descartados.
Se o usuário voltar a rolar, eles serão reconstruídos.
Isso pode parecer ineficiente.
Mas criar Widgets é extremamente barato.
Na maioria dos casos, reconstruir um widget custa muito menos do que manter milhares deles ocupando memória.
Esse equilíbrio entre CPU e memória é um dos pilares do desempenho do Flutter.
Como o Flutter sabe quais itens construir?
Essa é justamente a função do itemBuilder.
Perceba que você nunca entrega uma lista pronta de widgets.
Você entrega uma função.
itemBuilder: (context, index) {
return ProductTile(products[index]);
}
Essa função funciona como uma fábrica.
Sempre que o Flutter precisa do item 37, ele chama:
itemBuilder(context, 37)
Quando precisa do item 891:
itemBuilder(context, 891)
Você nunca precisa criar todos os widgets manualmente.
Eles surgem apenas quando são necessários.
Os RenderObjects envolvidos
Sem entrar profundamente na Render Tree, vale conhecer alguns nomes importantes.
Quando usamos um ListView, o Flutter cria uma estrutura especializada para lidar com rolagem.
Entre os RenderObjects envolvidos estão componentes responsáveis por:
- controlar a viewport (a janela visível);
- calcular quais filhos precisam existir;
- posicionar cada item;
- descartar itens que ficaram muito distantes da tela;
- solicitar novos itens ao
itemBuilder.
Você dificilmente precisará interagir diretamente com essas classes no dia a dia.
Mas entender que elas existem ajuda a explicar por que listas no Flutter são tão eficientes.
Mais importante ainda: ajuda a compreender por que algumas combinações de widgets podem gerar erros de layout, consumo excessivo de memória ou perda de performance.
O ListView parece simples porque ele esconde uma arquitetura complexa
Uma das maiores qualidades do Flutter é esconder sistemas extremamente sofisticados atrás de APIs pequenas.
Você escreve poucas linhas:
ListView.builder(...)
Mas por trás delas existe toda uma infraestrutura responsável por:
- virtualização da lista;
- criação sob demanda;
- cálculo de layout;
- gerenciamento de memória;
- renderização incremental;
- sincronização do scroll.
Tudo isso acontece automaticamente.
E ainda nem começamos a falar sobre a tecnologia que torna isso possível.
Conclusão
Neste artigo vimos que um ListView está longe de ser apenas um widget que exibe itens.
Ele faz parte de uma arquitetura de renderização pensada para criar interfaces altamente performáticas, mesmo quando lidamos com milhares de elementos.
Entender esse fluxo muda a forma como enxergamos listas no Flutter. Em vez de pensar em “uma coleção de widgets”, começamos a pensar em uma janela dinâmica onde apenas o que é necessário existe em memória.
Esse conhecimento também prepara o terreno para compreender comportamentos aparentemente estranhos, como erros envolvendo múltiplos widgets roláveis, problemas de layout com shrinkWrap ou a necessidade de usar CustomScrollView em cenários mais avançados.
No próximo artigo vamos revelar a peça que torna tudo isso possível.
Na verdade, o
ListViewé apenas um wrapper para algo muito mais poderoso: as Slivers. Vamos abrir essa caixa-preta e entender como o Flutter constrói uma tela rolável de verdade.



