Route — qué es, tipos y creación de rutas en Flutter

Autor: IT Sectr Publicado: 2026-07-02 Tiempo de lectura: 8 min

Route es una clase abstracta en Flutter que representa una pantalla o página individual en el historial de navegación de Navigator. Las implementaciones concretas de Route — MaterialPageRoute, CupertinoPageRoute y PlatformRoute — determinan cómo se muestra la pantalla y qué animación se utiliza durante la transición. A diferencia de un widget normal, Route tiene su propio ciclo de vida con los métodos didPush, didPop, didReplace y didChangeNext. Según la Flutter API Reference (2026), cada Route gestiona ModalBarrier, tiene en cuenta las características específicas de la plataforma (deslizar hacia atrás en iOS) y garantiza el aislamiento del estado entre pantallas.

Puntos clave

  • Route — una clase abstracta de pantalla en Flutter con su propio ciclo de vida (didPush, didPop, didReplace, didChangeNext)
  • MaterialPageRoute — la implementación estándar de Route con animación Material (deslizar desde abajo) para Android y escritorio
  • CupertinoPageRoute — implementación de Route con animación iOS (deslizar desde la derecha + gesto de deslizar hacia atrás) para iPhone y iPad
  • Ciclo de vida — Route pasa por las etapas: Transición, Activo, Inactivo y Destruido
  • Transferencia de datos — Route acepta argumentos a través del constructor y devuelve un resultado mediante Future al finalizar

Qué es Route en Flutter

Route es la base del sistema de navegación de Flutter. Cada pantalla que el usuario ve en una aplicación está representada por un objeto Route ubicado en la pila de Navigator. Route abstrae la pantalla del código de control: Navigator añade y elimina Route, mientras que dentro de Route está la interfaz que ve el usuario. Esta arquitectura separa la responsabilidad entre la navegación y la visualización.

A diferencia del simple reemplazo de widgets, Route proporciona servicios no disponibles en los widgets normales: ModalBarrier (oscurecimiento del fondo cuando hay un diálogo abierto), control de animación de entrada y salida, manejo del botón de retroceso físico en Android e integración con la animación Hero para transiciones suaves entre pantallas.

Según Flutter Cookbook (2026), Route es un elemento clave para la animación Hero: un widget Hero en una Route anima automáticamente la transición a un widget Hero en la siguiente Route, creando un efecto de elemento “virtual”. Esto es posible precisamente porque Route mantiene ambas pantallas en la superposición durante la animación.

Route como bloque de construcción de navegación

Route es la base tanto para aplicaciones móviles simples (a través de Navigator 1.0) como para escenarios complejos con enlaces profundos (Navigator 2.0). En Navigator 2.0, Route representa una Page que RouterDelegate convierte a partir de la configuración de la ruta. Por lo tanto, entender Route es esencial para trabajar con cualquier sistema de navegación de Flutter, independientemente del enfoque o paquete elegido.

Tipos de Route: MaterialPageRoute y CupertinoPageRoute

Flutter proporciona varias implementaciones integradas de Route, cada una adaptando el comportamiento a una plataforma específica. Elegir el tipo correcto de Route afecta la experiencia del usuario: la animación Material en Android y la animación Cupertino en iOS crean la sensación de una aplicación “nativa”.

Tipo de RouteAnimaciónPlataformaCaracterísticas
MaterialPageRouteDeslizar de abajo arribaAndroid, escritorioSombra en la transición, manejo automático de SafeArea
CupertinoPageRouteDeslizar de derecha a izquierdaiOS, iPadOSGesto de deslizar hacia atrás, fondo transparente durante la transición
PlatformRouteSelección automáticaTodas las plataformasSelecciona el tipo basado en TargetPlatform
PageRouteBuilderPersonalizadaTodas las plataformasControl total sobre la animación mediante AnimationController

MaterialPageRoute: estándar para Android

MaterialPageRoute es la implementación de Route más utilizada. Anima la entrada de la nueva pantalla de abajo arriba con aparición gradual. Al salir, la pantalla se anima de arriba abajo, volviendo a su posición original. La barra de herramientas (AppBar) y el cuerpo de la pantalla se animan por separado, creando un efecto de jerarquía.

CupertinoPageRoute: estilo de navegación iOS

CupertinoPageRoute imita UINavigationController de iOS. La nueva pantalla entra desde la derecha, cubriendo la anterior. La característica clave es el soporte para el gesto interactivo de deslizar hacia atrás, implementado a través de CupertinoBackGestureDetector. Este gesto se maneja incluso durante la animación, proporcionando un comportamiento natural familiar para los usuarios de iPhone.

Ciclo de vida de Route: desde la creación hasta la destrucción

Route tiene su propio ciclo de vida, que difiere del ciclo de vida de un StatefulWidget normal. Comprender este ciclo es necesario para la inicialización adecuada de datos, suscripciones a streams y liberación de recursos al cerrar una pantalla.

Etapas del ciclo de vida de Route

El ciclo de vida de Route consta de cuatro etapas principales. Transición — Route se crea y se anima al entrar (se llama a didPush). Activo — Route se muestra completamente e interactúa con el usuario. Inactivo — otra Route cubre la actual (diálogo, hoja inferior), pero Route permanece en la pila. Destruido — Route se elimina de la pila y se destruye, se llaman a didPop y dispose.

Los métodos del ciclo de vida de Route pueden ser sobreescritos en una implementación personalizada. Por ejemplo, didPop se llama cuando Route se elimina de la pila — aquí se pueden guardar datos de borrador. didChangeNext se llama cuando la siguiente Route en la pila ha cambiado — útil para actualizar la interfaz cuando cambia el historial de navegación.

Según Flutter API Route.didPop (2026), es importante no confundir el ciclo de vida de Route con el ciclo de vida del State dentro de Route. StatefulWidget dentro de Route tiene su propio initState y dispose, que se llaman durante las etapas de Transición y Destruido respectivamente. Route vive más que su State interno — Route permanece en la superposición incluso cuando sus widgets están temporalmente ocultos por otra Route.

Paso de datos a través de Route entre pantallas

Route proporciona mecanismos para pasar datos tanto en la entrada (al crearse) como en la salida (al finalizar). El paso adecuado de datos a través de Route elimina la necesidad de variables globales e InheritedWidget, haciendo la navegación segura en cuanto a tipos y predecible.

Para pasar datos a una nueva pantalla, use el constructor del widget receptor o el parámetro arguments en Navigator.pushNamed. Dentro de Route, los datos son accesibles a través de RouteSettings.arguments, que se almacena en el objeto Route. Este enfoque funciona para todos los tipos de Route — MaterialPageRoute, CupertinoPageRoute e implementaciones personalizadas.

Para devolver datos, use el segundo argumento de Navigator.pop(context, result). Navigator.push devuelve Future, que se completa con el valor pasado a pop. Si pop se llama sin argumento, Future se completa con null. Este mecanismo es análogo a startActivityForResult en Android y al completion handler en iOS, pero implementado mediante Dart Futures.

Paso de datos a través del constructor de Route

Al llamar a Navigator.push directamente con MaterialPageRoute, los datos se pasan a través del constructor de la pantalla de destino. No se utiliza MethodChannel — esta es una interacción pura de Dart. Este enfoque es preferible para el paso seguro de tipos de objetos complejos.

Ejemplo de creación de Route personalizado

Veamos un ejemplo de creación de un Route personalizado con su propia animación y paso de datos. PageRouteBuilder permite definir animaciones de entrada y salida con control total sobre la curva de animación y la duración.

dart
// Ruta personalizada con animación de deslizamiento
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),
));

// Devolver datos desde la pantalla
ElevatedButton(
  onPressed: () => Navigator.of(context).pop({'selected': true, 'id': '42'}),
  child: const Text('Seleccionar'),
);

// Obtener resultado en la pantalla de llamada
final result = await Navigator.push(context, MaterialPageRoute(
  builder: (context) => const SelectionPage(),
));
if (result != null) {
  print('Seleccionado: ${result['selected']}');
}

En el ejemplo, PageRouteBuilder define una animación personalizada de deslizamiento desde abajo con transparencia. transitionDuration establece la velocidad de la animación. El código también demuestra el paso de resultados: la pantalla de detalle devuelve un Map con la selección del usuario, y la pantalla de llamada recibe estos datos a través del Future de push. Route garantiza un aislamiento completo: los borradores en la pantalla de detalle no afectan el estado de la lista.

Preguntas frecuentes

¿Cuál es la diferencia entre Route y Widget en Flutter?

Route es un objeto que gestiona una pantalla a nivel de navegación: almacena animación, ModalBarrier y ciclo de vida. Widget es una descripción de una parte de la interfaz. Route contiene Widget dentro de sí mismo, pero también proporciona servicios (capa de superposición, animación Hero) no disponibles para los widgets normales. Una Route puede contener una jerarquía compleja de widgets de cualquier profundidad.

¿Cómo crear un Route con animación personalizada?

Use PageRouteBuilder con los parámetros pageBuilder (construcción de pantalla) y transitionsBuilder (definición de animación). En transitionsBuilder están disponibles animation (0.0–1.0) y secondaryAnimation para animaciones paralelas. Para control total, cree una subclase de Route y sobreescriba buildPage, createAnimationController y buildTransitions, dando acceso a AnimationController de bajo nivel.

¿Cómo pasar un objeto complejo entre Route?

Para pasar objetos complejos, use el constructor de la pantalla de destino al llamar a Navigator.push directamente o el parámetro arguments con pushNamed. Asegúrese de que el objeto sea serializable (Map, JSON o clase personalizada). Para el paso seguro de tipos en Flutter, use modelos freezed o json_serializable, que garantizan una deserialización correcta al pasar a través de RouteSettings.

¿Por qué Route podría no llamar a dispose?

Route.dispose no se llama si Route permanece en la pila de Navigator. Por ejemplo, al abrir una nueva Route, la Route anterior pasa al estado inactivo pero no se destruye — permanece en la pila para un retorno rápido. Dispose se llama solo cuando Route se elimina de la pila mediante pop, pushReplacement o pushAndRemoveUntil. Para liberar recursos, use dispose del State dentro de Route, no el dispose de la propia Route.

¿Cómo verificar qué Route está activa actualmente?

Use ModalRoute.of(context) para obtener la Route actual desde BuildContext. La propiedad ModalRoute.isActive muestra si la Route es la pantalla visible actualmente. ModalRoute.isCurrent — true si la Route es la parte superior de la pila. Para observar cambios en la pila, suscríbase a los observadores de Navigator a través de RouteAware y RouteObserver, que notifican sobre cambios de Route activa.

Resumen

  • Route — una clase abstracta de pantalla en Flutter con un ciclo de vida (didPush, didPop, didReplace, didChangeNext) y soporte para ModalBarrier y animación Hero
  • MaterialPageRoute — implementación para Android con animación de deslizamiento desde abajo, sombra y SafeArea automática
  • CupertinoPageRoute — implementación para iOS con animación de deslizamiento desde la derecha y gesto interactivo de deslizar hacia atrás
  • PageRouteBuilder — utilidad para crear Route con animación personalizada mediante transitionsBuilder y AnimationController
  • Paso de datos — a través del constructor de Route (push) o arguments (pushNamed) en la entrada; mediante Navigator.pop(context, result) en la salida con Future
  • Ciclo de vida — cuatro etapas: Transición (didPush), Activo, Inactivo (cubierto por otra Route), Destruido (didPop + dispose)
  • Aislamiento de pantallas — cada Route tiene su propio BuildContext y estado, lo que previene fugas y simplifica la gestión de datos

Desarrollaremos una aplicación móvil llave en mano

IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.

Discutir el proyecto

Lea también