Saltar al contenido principal

Actualizaciones del registro de transición de ruta y del transition delegate

Cambios en la regla sobre cómo el transition delegate resuelve la transición de ruta.

Resumen

#

Se añadió un nuevo getter booleano isWaitingForExitingDecision al registro de transición de ruta y el getter isEntering se renombró a isWaitingForEnteringDecision. En el método resolve() para el transition delegate, usa isWaitingForExitingDecision para verificar si una ruta de salida realmente necesita una decisión explícita sobre cómo transicionar fuera de la pantalla. Si intentas tomar una decisión para una ruta existente que no está esperando una decisión, Flutter lanzará un error de aserción.

Contexto

#

Cuando el navigator recibe una nueva lista de pages, intenta actualizar su pila de rutas actual para que coincida con la lista. Sin embargo, requiere decisiones explícitas sobre cómo transicionar la ruta hacia y fuera de la pantalla. Anteriormente, las rutas que no estaban en la nueva lista requerían decisiones sobre cómo transicionar fuera de la pantalla. Sin embargo, más tarde descubrimos que esto no siempre es así. Si una ruta se hace pop, pero aún está esperando que termine la animación de pop, esta ruta permanecería en la pila de rutas del navigator hasta que terminara la animación. Si ocurriera una actualización de page durante este tiempo, esta ruta saldría pero no requeriría una decisión sobre cómo transicionar fuera de la pantalla. Por lo tanto, se añadió isWaitingForExitingDecision para cubrir ese caso.

El getter isEntering también se renombró a isWaitingForEnteringDecision para ser más descriptivo, y también para hacer que la nomenclatura sea más consistente.

Guía de migración

#

Si implementas tu propio transition delegate, necesitas verificar las rutas salientes usando el getter isWaitingForExitingDecision antes de llamar a markForPop, markForComplete o markForRemove en ellas. También necesitas renombrar todas las referencias de isEntering a isWaitingForEnteringDecision.

Código antes de la migración:

dart
import 'package:flutter/widgets.dart';

class NoAnimationTransitionDelegate extends TransitionDelegate<void> {
  @override
  Iterable<RouteTransitionRecord> resolve({
    List<RouteTransitionRecord> newPageRouteHistory,
    Map<RouteTransitionRecord, RouteTransitionRecord> locationToExitingPageRoute,
    Map<RouteTransitionRecord, List<RouteTransitionRecord>> pageRouteToPagelessRoutes,
  }) {
    final List<RouteTransitionRecord> results = <RouteTransitionRecord>[];

    for (final RouteTransitionRecord pageRoute in newPageRouteHistory) {
      if (pageRoute.isEntering) {
        pageRoute.markForAdd();
      }
      results.add(pageRoute);

    }
    for (final RouteTransitionRecord exitingPageRoute in locationToExitingPageRoute.values) {
      exitingPageRoute.markForRemove();
      final List<RouteTransitionRecord> pagelessRoutes = pageRouteToPagelessRoutes[exitingPageRoute];
      if (pagelessRoutes != null) {
        for (final RouteTransitionRecord pagelessRoute in pagelessRoutes) {
          pagelessRoute.markForRemove();
        }
      }
      results.add(exitingPageRoute);

    }
    return results;
  }
}

Código después de la migración:

dart
import 'package:flutter/widgets.dart';

class NoAnimationTransitionDelegate extends TransitionDelegate<void> {
  @override
  Iterable<RouteTransitionRecord> resolve({
    List<RouteTransitionRecord> newPageRouteHistory,
    Map<RouteTransitionRecord, RouteTransitionRecord> locationToExitingPageRoute,
    Map<RouteTransitionRecord, List<RouteTransitionRecord>> pageRouteToPagelessRoutes,
  }) {
    final List<RouteTransitionRecord> results = <RouteTransitionRecord>[];

    for (final RouteTransitionRecord pageRoute in newPageRouteHistory) {
      // Renames isEntering to isWaitingForEnteringDecision.
      if (pageRoute.isWaitingForEnteringDecision) {
        pageRoute.markForAdd();
      }
      results.add(pageRoute);

    }
    for (final RouteTransitionRecord exitingPageRoute in locationToExitingPageRoute.values) {
      // Checks the isWaitingForExitingDecision before calling the markFor methods.
      if (exitingPageRoute.isWaitingForExitingDecision) {
        exitingPageRoute.markForRemove();
        final List<RouteTransitionRecord> pagelessRoutes = pageRouteToPagelessRoutes[exitingPageRoute];
        if (pagelessRoutes != null) {
          for (final RouteTransitionRecord pagelessRoute in pagelessRoutes) {
            pagelessRoute.markForRemove();
          }
        }
      }
      results.add(exitingPageRoute);

    }
    return results;
  }
}

Timeline

#

Introducido en la versión: 1.18.0
En la versión estable: 1.20

Referencias

#

Documentación de la API:

Problema relevante:

PR relevante:

  • PR 55998: Corrige el fallo de actualización de pages del navigator cuando todavía hay una ruta esperando