Route — o que é, tipos e criação de rotas no Flutter

Autor: IT Sectr Publicado: 2026-07-02 Tempo de leitura: 8 min

Route é uma classe abstrata no Flutter que representa uma tela ou página separada no histórico de navegação do Navigator. As implementações concretas de Route — MaterialPageRoute, CupertinoPageRoute e PlatformRoute — determinam como a tela é exibida e qual animação é usada durante a transição. Ao contrário de um widget comum, Route tem seu próprio ciclo de vida com os métodos didPush, didPop, didReplace e didChangeNext. De acordo com a Flutter API Reference (2026), cada Route gerencia ModalBarrier, leva em conta características específicas da plataforma (deslizar para trás no iOS) e garante o isolamento de estado entre telas.

Pontos principais

  • Route — uma classe abstrata de tela no Flutter com seu próprio ciclo de vida (didPush, didPop, didReplace, didChangeNext)
  • MaterialPageRoute — a implementação padrão de Route com animação Material (deslizar de baixo) para Android e desktop
  • CupertinoPageRoute — implementação de Route com animação iOS (deslizar da direita + gesto de deslizar para trás) para iPhone e iPad
  • Ciclo de vida — Route passa por estágios: Transição, Ativo, Inativo e Descartado
  • Transferência de dados — Route aceita argumentos através do construtor e retorna um resultado via Future quando concluído

O que é Route no Flutter

Route é a base do sistema de navegação do Flutter. Cada tela que o usuário vê em um aplicativo é representada por um objeto Route localizado na pilha do Navigator. Route abstrai a tela do código de controle: Navigator adiciona e remove Route, enquanto dentro de Route está a interface que o usuário vê. Esta arquitetura separa a responsabilidade entre navegação e exibição.

Ao contrário da simples substituição de widgets, Route fornece serviços indisponíveis para widgets comuns: ModalBarrier (escurecimento do fundo quando um diálogo está aberto), controle de animação de entrada e saída, manipulação do botão físico de voltar no Android e integração com animação Hero para transições suaves entre telas.

De acordo com Flutter Cookbook (2026), Route é um elemento chave para animação Hero: um widget Hero em uma Route anima automaticamente a transição para um widget Hero na próxima Route, criando um efeito de elemento “voando”. Isso é possível precisamente porque Route mantém ambas as telas no Overlay durante a animação.

Route como bloco de construção da navegação

Route é a base tanto para aplicativos móveis simples (através do Navigator 1.0) quanto para cenários complexos com links profundos (Navigator 2.0). No Navigator 2.0, Route representa uma Page que o RouterDelegate converte a partir da configuração de rota. Portanto, entender Route é essencial para trabalhar com qualquer sistema de navegação do Flutter — independentemente da abordagem ou pacote escolhido.

Tipos de Route: MaterialPageRoute e CupertinoPageRoute

Flutter fornece várias implementações embutidas de Route, cada uma adaptando o comportamento a uma plataforma específica. Escolher o tipo correto de Route afeta a experiência do usuário: animação Material no Android e animação Cupertino no iOS criam a sensação de um aplicativo “nativo”.

Tipo de RouteAnimaçãoPlataformaCaracterísticas
MaterialPageRouteDeslizar de baixo para cimaAndroid, desktopSombra na transição, manipulação automática de SafeArea
CupertinoPageRouteDeslizar da direita para esquerdaiOS, iPadOSGesto de deslizar para trás, fundo transparente durante a transição
PlatformRouteSeleção automáticaTodas as plataformasSeleciona o tipo com base no TargetPlatform
PageRouteBuilderPersonalizadaTodas as plataformasControle total sobre a animação através de AnimationController

MaterialPageRoute: padrão para Android

MaterialPageRoute é a implementação de Route mais usada. Ela anima a nova tela entrando de baixo para cima com aparecimento gradual. Ao sair, a tela anima de cima para baixo, retornando à sua posição original. A barra de ferramentas (AppBar) e o corpo da tela animam separadamente, criando um efeito de hierarquia.

CupertinoPageRoute: estilo de navegação iOS

CupertinoPageRoute imita o UINavigationController do iOS. A nova tela entra pela direita, cobrindo a anterior. A característica chave é o suporte ao gesto interativo de deslizar para trás, implementado através de CupertinoBackGestureDetector. Este gesto é manipulado mesmo durante a animação, proporcionando um comportamento natural familiar aos usuários de iPhone.

Ciclo de vida da Route: da criação ao descarte

Route tem seu próprio ciclo de vida, que difere do ciclo de vida de um StatefulWidget comum. Compreender este ciclo é necessário para a inicialização adequada de dados, inscrições em streams e liberação de recursos ao fechar uma tela.

Estágios do ciclo de vida da Route

O ciclo de vida da Route consiste em quatro estágios principais. Transição — Route é criada e animada na entrada (didPush é chamado). Ativo — Route é totalmente exibida e interage com o usuário. Inativo — outra Route cobre a atual (diálogo, folha inferior), mas a Route permanece na pilha. Descartado — Route é removida da pilha e destruída, didPop e dispose são chamados.

Os métodos do ciclo de vida de Route podem ser sobrescritos em uma implementação personalizada. Por exemplo, didPop é chamado quando Route é removida da pilha — aqui você pode salvar dados de rascunho. didChangeNext é chamado quando a próxima Route na pilha mudou — útil para atualizar a UI quando o histórico de navegação muda.

De acordo com Flutter API Route.didPop (2026), é importante não confundir o ciclo de vida da Route com o ciclo de vida do State dentro da Route. StatefulWidget dentro de Route tem seu próprio initState e dispose, que são chamados durante os estágios de Transição e Descartado respectivamente. Route vive mais que seu State interno — Route permanece no Overlay mesmo quando seus widgets estão temporariamente ocultos por outra Route.

Passagem de dados via Route entre telas

Route fornece mecanismos para passar dados tanto na entrada (quando criada) quanto na saída (quando concluída). A passagem adequada de dados via Route elimina a necessidade de variáveis globais e InheritedWidget, tornando a navegação type-safe e previsível.

Para passar dados para uma nova tela, use o construtor do widget receptor ou o parâmetro arguments no Navigator.pushNamed. Dentro de Route, os dados são acessíveis através de RouteSettings.arguments, que é armazenado no objeto Route. Esta abordagem funciona para todos os tipos de Route — MaterialPageRoute, CupertinoPageRoute e implementações personalizadas.

Para retornar dados, use o segundo argumento de Navigator.pop(context, result). Navigator.push retorna Future, que é concluído com o valor passado para pop. Se pop for chamado sem argumento, Future é concluído com null. Este mecanismo é análogo ao startActivityForResult no Android e ao completion handler no iOS, mas implementado através de Dart Futures.

Passagem de dados através do construtor de Route

Ao chamar Navigator.push diretamente com MaterialPageRoute, os dados são passados através do construtor da tela de destino. MethodChannel não é usado — esta é uma interação pura de Dart. Esta abordagem é preferível para passagem type-safe de objetos complexos.

Exemplo de criação de Route personalizado

Vamos ver um exemplo de criação de um Route personalizado com sua própria animação e passagem de dados. PageRouteBuilder permite definir animações de entrada e saída com controle total sobre a curva de animação e duração.

dart
// Route personalizado com animação de deslizamento
Navigator.push(context, PageRouteBuilder(
  pageBuilder: (context, animation, secondaryAnimation) {
    return DetailPage(productId: '42');
  },
  transitionsBuilder: (context, animation, secondaryAnimation, child) {
    const begin = Offset(0.0, 0.3);
    const end = Offset.zero;
    final tween = Tween(begin: begin, end: end);
    final offsetAnimation = animation.drive(tween);
    return SlideTransition(position: offsetAnimation, child: child);
  },
  transitionDuration: const Duration(milliseconds: 400),
));

// Retornar dados da tela
ElevatedButton(
  onPressed: () => Navigator.of(context).pop({'selected': true, 'id': '42'}),
  child: const Text('Selecionar'),
);

// Obter resultado na tela de chamada
final result = await Navigator.push(context, MaterialPageRoute(
  builder: (context) => const SelectionPage(),
));
if (result != null) {
  print('Selecionado: ${result['selected']}');
}

No exemplo, PageRouteBuilder define uma animação personalizada de deslizamento de baixo com transparência. transitionDuration define a velocidade da animação. O código também demonstra a passagem de resultado: a tela de detalhe retorna um Map com a seleção do usuário, e a tela de chamada recebe estes dados através do Future do push. Route garante isolamento completo: rascunhos na tela de detalhe não afetam o estado da lista.

Perguntas frequentes

Qual a diferença entre Route e Widget no Flutter?

Route é um objeto que gerencia uma tela no nível de navegação: armazena animação, ModalBarrier e ciclo de vida. Widget é uma descrição de uma parte da interface. Route contém Widget dentro de si, mas também fornece serviços (camada Overlay, animação Hero) indisponíveis para widgets comuns. Uma Route pode conter uma hierarquia complexa de widgets de qualquer profundidade.

Como criar um Route com animação personalizada?

Use PageRouteBuilder com os parâmetros pageBuilder (construção da tela) e transitionsBuilder (definição da animação). Em transitionsBuilder, estão disponíveis animation (0.0–1.0) e secondaryAnimation para animações paralelas. Para controle total, crie uma subclasse de Route e sobrescreva buildPage, createAnimationController e buildTransitions, dando acesso a AnimationController de baixo nível.

Como passar um objeto complexo entre Route?

Para passar objetos complexos, use o construtor da tela de destino ao chamar Navigator.push diretamente ou o parâmetro arguments com pushNamed. Certifique-se de que o objeto seja serializável (Map, JSON ou classe personalizada). Para passagem type-safe no Flutter, use modelos freezed ou json_serializable, que garantem desserialização correta ao passar via RouteSettings.

Por que Route pode não chamar dispose?

Route.dispose não é chamado se Route permanecer na pilha do Navigator. Por exemplo, ao abrir uma nova Route, a Route antiga vai para o estado inativo mas não é destruída — permanece na pilha para retorno rápido. Dispose é chamado apenas quando Route é removida da pilha via pop, pushReplacement ou pushAndRemoveUntil. Para liberar recursos, use o dispose do State dentro de Route, não o dispose da própria Route.

Como verificar qual Route está ativa atualmente?

Use ModalRoute.of(context) para obter a Route atual do BuildContext. A propriedade ModalRoute.isActive mostra se a Route é a tela atualmente visível. ModalRoute.isCurrent — true se a Route é o topo da pilha. Para observar mudanças na pilha, inscreva-se nos observadores do Navigator através de RouteAware e RouteObserver, que notificam sobre mudanças de Route ativa.

Resumo

  • Route — uma classe abstrata de tela no Flutter com ciclo de vida (didPush, didPop, didReplace, didChangeNext) e suporte para ModalBarrier e animação Hero
  • MaterialPageRoute — implementação para Android com animação de deslizamento de baixo, sombra e SafeArea automática
  • CupertinoPageRoute — implementação para iOS com animação de deslizamento da direita e gesto interativo de deslizar para trás
  • PageRouteBuilder — utilitário para criar Route com animação personalizada através de transitionsBuilder e AnimationController
  • Passagem de dados — através do construtor de Route (push) ou arguments (pushNamed) na entrada; via Navigator.pop(context, result) na saída com Future
  • Ciclo de vida — quatro estágios: Transição (didPush), Ativo, Inativo (coberto por outra Route), Descartado (didPop + dispose)
  • Isolamento de telas — cada Route tem seu próprio BuildContext e estado, prevenindo vazamentos e simplificando o gerenciamento de dados

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