RenderObject Tree: o que é, princípios de renderização e seu papel no Flutter

Autor: IT Sectr Publicado: 2026-07-01 Tempo de leitura: 9 min

RenderObject Tree é o terceiro nível da hierarquia do Flutter, responsável pela renderização real da interface na tela. Cada nó desta árvore realiza o cálculo de tamanhos (layout) e a pintura (painting), convertendo a configuração dos widgets em pixels. Ao contrário da Widget Tree, a RenderObject Tree é criada uma vez e atualizada apenas quando a geometria ou a aparência mudam. De acordo com a Referência da API Flutter, 2025, a eficiência da RenderObject Tree determina diretamente a suavidade das animações e a capacidade de resposta da aplicação.

Pontos principais

  • RenderObject Tree é uma hierarquia de objetos de renderização que calculam tamanhos e desenham a interface na tela.
  • Cada RenderObject realiza duas fases: layout (determinação de tamanhos e posições) e paint (desenho de pixels).
  • RenderObject Tree é criada a partir da Element Tree e sincronizada com ela através dos elementos.
  • RepaintBoundary isola parte da árvore para repintura local sem afetar toda a tela.
  • O desempenho da RenderObject Tree depende da profundidade, número de camadas e frequência de repintura.

O que é a RenderObject Tree no Flutter?

RenderObject Tree é uma estrutura hierárquica de objetos de renderização que serve como a representação real da interface na memória. Cada RenderObject conhece seu próprio tamanho, posição na tela e como se desenhar. Ao contrário dos widgets, que são leves e podem ser recriados centenas de vezes por segundo, um RenderObject é um objeto pesado com acesso direto ao pipeline gráfico.

Da configuração à renderização

O caminho do widget aos pixels passa por três etapas: a Widget Tree descreve o que deve estar na tela; a Element Tree gerencia o ciclo de vida; a RenderObject Tree realiza o trabalho real. Cada RenderObjectWidget (como Padding, Transform, CustomPaint) cria um RenderObject que é adicionado à árvore de renderização. RenderBox é o tipo mais comum de RenderObject, usado por 99% dos widgets padrão.

Arquitetura do RenderObject

RenderObject é uma classe abstrata que define a interface para layout e paint. Ela contém referências ao RenderObject pai e aos objetos filhos, bem como métodos abstratos: performLayout, paint e hitTest. Cada RenderObject concreto implementa esses métodos de acordo com seu comportamento: RenderFlex distribui espaço entre os filhos, RenderImage exibe uma imagem, RenderParagraph renderiza texto.

dart
abstract class RenderObject {
  RenderObject? parent;
  Constraints constraints;
  ParentData? parentData;
  bool _needsLayout = true;
  bool _needsPaint = true;

  void performLayout();
  void paint(PaintingContext context, Offset offset);
}

Nesta estrutura simplificada, RenderObject contém os flags _needsLayout e _needsPaint, que marcam o objeto como necessitando de atualização. Quando a Widget Tree muda, a Element Tree marca os RenderObjects correspondentes como “ sujos” para layout ou paint, e no próximo frame o Flutter realiza apenas as operações necessárias.

Duas fases do RenderObject: layout e paint

Cada RenderObject realiza duas fases principais: layout (determinação de tamanhos e posições) e paint (desenho). Essas fases são executadas em ordem estrita: primeiro layout para toda a árvore, depois paint. A fase de paint pode ser pulada se o layout não mudou, economizando recursos da GPU.

Fase de layout: restrições e tamanhos

Durante o layout, o Flutter passa restrições (constraints) de cima para baixo através da RenderObject Tree. Cada pai define largura e altura mínima e máxima para seu filho. O filho calcula seu tamanho dentro dessas restrições e o retorna ao pai. Este processo é chamado de “passagem descendente” (passar restrições para baixo) e “passagem ascendente” (passar tamanhos para cima).

  • BoxConstraints é o tipo mais comum de restrição: minWidth, maxWidth, minHeight, maxHeight.
  • SliverConstraints é usado no ScrollView para virtualização: adiciona informação de rolagem às restrições padrão.
  • RenderSliverMultiBoxAdaptor gerencia o layout de listas virtualizadas, criando RenderObjects apenas para os itens visíveis.

Fase de paint: exibição na tela

Após completar o layout, o Flutter realiza o paint — desenho de cada RenderObject. O pai cria um PaintingContext, passa para os objetos filhos e especifica o deslocamento (offset). Cada RenderObject se desenha no Canvas usando primitivas gráficas: retângulos, círculos, texto, imagens e transformações. O Canvas interage diretamente com Skia ou Impeller.

Marcação de nós sujos

O Flutter usa um mecanismo de nós “sujos” para minimizar o trabalho. Quando apenas o tamanho de um RenderObject muda, o Flutter não recalcula o layout de toda a árvore — ele marca o nó alterado e seus possíveis ancestrais até o RenderBox mais próximo com tamanho fixo. Da mesma forma, quando a aparência muda, apenas o paint é marcado sem refazer o layout.

Tipos de RenderObject no Flutter

O Flutter fornece várias categorias de RenderObject para diferentes tarefas: RenderBox para elementos retangulares padrão, RenderSliver para áreas roláveis e RenderObjects personalizados para renderização não padrão via CustomPainter. Cada tipo é otimizado para seu papel na árvore de renderização.

RenderBox e seus subtipos

RenderBox é a classe base para elementos de interface retangulares. Seus subtipos incluem: RenderPadding (adiciona preenchimento), RenderTransform (aplica transformações), RenderFlex (implementa Row e Column), RenderStack (sobrepõe elementos), RenderImage (exibe imagens), RenderParagraph (renderiza texto). Cada subtipo substitui performLayout e paint para sua própria lógica.

RenderSliver e virtualização

RenderSliver é um tipo de RenderObject para trabalhar com áreas roláveis. Ao contrário do RenderBox, o Sliver usa SliverConstraints, que incluem informações do viewport. RenderSliverList e RenderSliverGrid criam RenderObjects apenas para os itens na área visível, permitindo lidar com listas com milhões de entradas.

RenderObject personalizado via CustomPainter

Para gráficos não padrão, use CustomPaint e CustomPainter. CustomPaint cria RenderCustomPaint, que chama os métodos paint do CustomPainter. Isso permite desenhar formas arbitárias, gráficos e animações com controle total sobre o Canvas. De acordo com a equipe do Flutter, o CustomPainter é mais eficiente que widgets padrão aninhados para gráficos vetoriais complexos.

dart
class CirclePainter extends CustomPainter {
  final Color color;

  CirclePainter({required this.color});

  @override
  void paint(Canvas canvas, Size size) {
    final paint = Paint()..color = color;
    canvas.drawCircle(
      Offset(size.width / 2, size.height / 2),
      size.width / 3,
      paint,
    );
  }

  @override
  bool shouldRepaint(CirclePainter oldDelegate) =>
    oldDelegate.color != color;
}

Neste exemplo, CirclePainter desenha um círculo no Canvas. O método shouldRepaint retorna true apenas quando a cor muda, evitando repinturas desnecessárias. O CustomPainter deve ser o mais leve possível — realize todos os cálculos pesados fora dos métodos paint.

RenderObject Tree é criada a partir da Element Tree através do mecanismo RenderObjectWidget. Cada RenderObjectWidget (Padding, Transform, CustomPaint) cria um RenderObjectElement, que por sua vez cria e gerencia o RenderObject correspondente. O elemento atua como intermediário: passa a configuração do widget para o RenderObject e notifica o RenderObject sobre as mudanças.

Criação de um RenderObject a partir de um elemento

Quando um RenderObjectElement é montado, ele chama o método createRenderObject em seu widget. O widget cria uma instância de RenderObject e a retorna ao elemento. O elemento insere o RenderObject na RenderObject Tree chamando o método insertChildLayout no RenderObject pai. Este processo ocorre apenas na primeira montagem — em atualizações subsequentes, o elemento simplesmente atualiza os parâmetros do RenderObject existente.

Sincronização via updateRenderObject

Quando a configuração do widget muda (por exemplo, o valor de padding muda), o elemento chama o método updateRenderObject, que passa a nova configuração ao RenderObject existente. O RenderObject se marca como “ sujo” para layout ou paint, e no próximo frame o framework realiza as atualizações necessárias.

Remoção de um RenderObject

Quando um elemento é desmontado, o método unmount é chamado, que remove o RenderObject da RenderObject Tree e libera recursos. RenderObject.remove é chamado para se desconectar do pai, após o qual o objeto pode ser coletado pelo coletor de lixo. O Flutter garante que nenhum RenderObject fique pendurado na árvore sem um elemento correspondente.

RepaintBoundary e isolamento de renderização

RepaintBoundary é um widget que cria uma camada separada para renderizar seu conteúdo. Quando o conteúdo dentro de um RepaintBoundary muda, apenas essa camada é repintada, enquanto o resto da tela permanece inalterado. RepaintBoundary é especialmente útil para animações, players de vídeo, gráficos interativos e outros elementos atualizados com frequência.

Como funciona o RepaintBoundary

No núcleo do RepaintBoundary está RenderRepaintBoundary — um RenderObject especial que cria um PictureLayer separado. Na primeira renderização, o RenderRepaintBoundary grava comandos gráficos nesta camada. Em atualizações subsequentes, se apenas o conteúdo dentro do RepaintBoundary mudar, o Flutter repinta apenas esta camada em vez de toda a tela. As outras camadas permanecem inalteradas e são reutilizadas.

Quando usar RepaintBoundary

Nem todo widget precisa de RepaintBoundary. Use-o quando uma parte da interface atualiza com alta frequência (60 FPS ou mais) enquanto o resto da tela é estático. Exemplos típicos: um indicador de carregamento animado, player de vídeo, Canvas de jogo, CustomPainter com repinturas frequentes. Para texto estático ou botões, RepaintBoundary é excessivo e só aumenta o consumo de memória.

CenárioRecomendaçãoMotivo
AnimaçãoEnvolver em RepaintBoundaryIsola a área frequentemente atualizada
Lista rolávelNão necessárioListView usa camadas automaticamente
Texto estáticoNão necessárioSem repinturas frequentes
CustomPainterRecomendadoRepinturas gráficas frequentes

Otimização da RenderObject Tree para desempenho

O desempenho da RenderObject Tree depende do número de nós, profundidade da árvore e frequência de repintura. O Flutter DevTools (a aba “Rendering”) permite analisar a RenderObject Tree em tempo real: contagem de repinturas, tempo de layout e paint, número de camadas e seus tamanhos. A análise regular ajuda a identificar gargalos.

Evite overdraw excessivo

Overdraw é uma situação em que um único pixel é desenhado várias vezes por frame. Por exemplo, quando um widget semitransparente se sobrepõe a outro, a GPU desenha ambas as camadas. Use flags opacos (Container com color em vez de decoration) para elementos não transparentes, para que o Flutter pule camadas invisíveis. De acordo com a equipe do Flutter, reduzir o overdraw pode diminuir o tempo de paint em até 30%.

Minimize o número de camadas

Cada RepaintBoundary e alguns widgets (Opacity, ClipRRect, Transform) criam uma camada separada (PictureLayer). Muitas camadas aumentam o tempo de composição. Use agrupamento: em vez de vários widgets Opacity em elementos individuais, aplique um único Opacity ao contêiner. Em vez de ClipRRect em cada elemento, use ClipRRect no contêiner comum.

Use construtores const

Quando um widget é declarado como const, o Flutter sabe que sua configuração não mudará e pode reutilizar o RenderObject correspondente sem recriá-lo. Construtores const reduzem a carga do coletor de lixo e aceleram o primeiro frame. Use const para widgets com parâmetros fixos: ícones, títulos, elementos decorativos.

dart
const Text("Title", style: TextStyle(fontSize: 24));
const Icon(Icons.home, color: Colors.blue);
const SizedBox.shrink();

Perguntas frequentes

Como a RenderObject Tree difere da Widget Tree?

Widget Tree é uma configuração leve de interface que é recriada a cada reconstrução. RenderObject Tree é uma árvore pesada de objetos de renderização que persiste e atualiza apenas quando a geometria ou aparência muda.

Como posso ver a RenderObject Tree no depurador?

Use Flutter DevTools — a aba “Rendering”. Você verá as camadas de renderização, tempo de layout e paint, e informações detalhadas de cada RenderObject: tamanhos, restrições e flags sujos.

O que é um RenderObject sujo?

Dirty é um RenderObject marcado como necessitando de atualização. O flag _needsLayout ou _needsPaint é definido quando a configuração muda, e o Flutter realiza layout ou paint para aquele nó no próximo frame.

Posso criar meu próprio RenderObject?

Sim, crie uma subclasse de RenderBox e substitua os métodos performLayout e paint. Use RenderObjectWidget para incorporar um RenderObject personalizado na Widget Tree. Esta é uma técnica avançada para renderização não padrão.

Como o RepaintBoundary afeta a RenderObject Tree?

RepaintBoundary cria RenderRepaintBoundary, que isola parte da RenderObject Tree em uma camada separada. Quando o conteúdo muda, apenas essa camada é repintada, deixando o resto da árvore inalterado.

Resumo

  • RenderObject Tree é o terceiro nível da arquitetura do Flutter, responsável pelo layout e paint de cada elemento da interface.
  • Cada RenderObject realiza duas fases: layout (cálculo de tamanhos e posições) e paint (desenho de pixels via Canvas).
  • RenderBox é o tipo base para elementos padrão, RenderSliver é para virtualizar listas roláveis.
  • RenderObject Tree é sincronizada com a Element Tree através de RenderObjectElement, que cria e atualiza RenderObjects.
  • RepaintBoundary isola parte da árvore em uma camada separada, evitando a repintura completa da tela em mudanças locais.
  • O desempenho depende da profundidade da árvore, número de camadas, overdraw e uso de construtores const.
  • Flutter DevTools fornece ferramentas para analisar a RenderObject Tree: tempo de layout, tempo de paint, número de camadas e repinturas.

Vamos desenvolver um aplicativo móvel chave na mão

A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.

Discutir o projeto

Leia também