Saltar al contenido principal

Refactorización de Route y Navigator

Algunas APIs y firmas de función de las clases Route y Navigator han cambiado.

Resumen

#

La clase Route ya no gestiona sus entradas de overlay en el overlay, y su método install() ya no tiene un parámetro insertionPoint. La propiedad isInitialRoute en RouteSetting ha sido depreciada, y Navigator.pop() ya no devuelve un valor.

Contexto

#

Refactorizamos las APIs del navigator para prepararnos para la nueva API de pages y la introducción del widget Router como se describe en el documento de diseño de Router. Esta refactorización introdujo algunos cambios en las firmas de funciones para que las APIs existentes del navigator sigan funcionando con la nueva API de pages.

Descripción del cambio

#

El valor de retorno booleano de Navigator.pop() no estaba bien definido, y el usuario podía lograr el mismo resultado llamando a Navigator.canPop(). Dado que la API para Navigator.canPop() estaba mejor definida, simplificamos Navigator.pop() para que no devuelva un valor booleano.

Por otro lado, el navigator requiere la capacidad de reorganizar manualmente las entradas en el overlay para permitir que el usuario cambie el historial de rutas en la nueva API. Lo cambiamos de manera que la ruta solo cree y destruya sus entradas de overlay, mientras que el navigator inserta o elimina entradas de overlay del overlay. También eliminamos el argumento insertionPoint de Route.install() porque era obsoleto después del cambio.

Finalmente, eliminamos la propiedad isInitialRoute de RouteSetting como parte de la refactorización, y proporcionamos la API onGenerateInitialRoutes para un control total de la generación de rutas iniciales.

Guía de migración

#

Caso 1: Una aplicación depende de que pop() devuelva un valor booleano.

dart
TextField(
  onTap: () {
    if (Navigator.pop(context))
      print('There still is at least one route after pop');
    else
      print('Oops! No more routes.');
  }
)

Podrías usar Navigator.canPop() en combinación con Navigator.pop() para lograr el mismo resultado.

dart
TextField(
  onTap: () {
    if (Navigator.canPop(context))
      print('There still is at least one route after pop');
    else
      print('Oops! No more routes.');
    // Our navigator pops the route anyway.
    Navigator.pop(context);
  }
)

Caso 2: Una aplicación genera rutas basándose en isInitialRoute.

dart
MaterialApp(
  onGenerateRoute: (RouteSetting setting) {
    if (setting.isInitialRoute)
      return FakeSplashRoute();
    else
      return RealRoute(setting);
  }
)

Hay diferentes maneras de migrar este cambio. Una forma es establecer un valor explícito para MaterialApp.initialRoute. Luego puedes verificar este valor en lugar de isInitialRoute. Como initialRoute hereda su valor por defecto fuera del alcance de Flutter, debes establecer un valor explícito para él.

dart
MaterialApp(
  initialRoute: '/', // Set this value explicitly. Default might be altered.
  onGenerateRoute: (RouteSetting setting) {
    if (setting.name == '/')
      return FakeSplashRoute();
    else
      return RealRoute(setting);
  }
)

Si hay un caso de uso más complicado, puedes usar la nueva API, onGenerateInitialRoutes, en MaterialApp o CupertinoApp.

dart
MaterialApp(
  onGenerateRoute: (RouteSetting setting) {
    return RealRoute(setting);
  },
  onGenerateInitialRoutes: (String initialRouteName) {
    return <Route>[FakeSplashRoute()];
  }
)

Timeline

#

Lanzado en la versión: 1.16.3
En versión estable: 1.17

Referencias

#

Doc de diseño:

Documentación de la API:

Problema relevante:

PR relevante:

  • PR 44930 - Refactorizar la API imperativa para que continúe funcionando en el nuevo sistema de navegación